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)); 80*66655411SSimon J. Gerraty if (nfip == NULL) { 81*66655411SSimon J. Gerraty #ifdef _STANDALONE 82*66655411SSimon J. Gerraty printf("%s: out of memory! %lu\n", __func__, 83*66655411SSimon J. Gerraty (unsigned long)sizeof(struct fingerprint_info)); 84*66655411SSimon J. Gerraty #endif 85*66655411SSimon J. Gerraty return; 86*66655411SSimon J. Gerraty } 875fff9558SSimon J. Gerraty if (prefix) { 885fff9558SSimon J. Gerraty nfip->fi_prefix = strdup(prefix); 895fff9558SSimon J. Gerraty } else { 905fff9558SSimon J. Gerraty if (!filename) { 915fff9558SSimon J. Gerraty free(nfip); 925fff9558SSimon J. Gerraty return; 935fff9558SSimon J. Gerraty } 945fff9558SSimon J. Gerraty nfip->fi_prefix = strdup(filename); 955fff9558SSimon J. Gerraty cp = strrchr(nfip->fi_prefix, '/'); 9653f151f9SSimon J. Gerraty if (cp == nfip->fi_prefix) { 9753f151f9SSimon J. Gerraty cp[1] = '\0'; 9853f151f9SSimon J. Gerraty } else if (cp) { 995fff9558SSimon J. Gerraty *cp = '\0'; 10053f151f9SSimon J. Gerraty } else { 1015fff9558SSimon J. Gerraty free(nfip->fi_prefix); 1025fff9558SSimon J. Gerraty free(nfip); 1035fff9558SSimon J. Gerraty return; 1045fff9558SSimon J. Gerraty } 1055fff9558SSimon J. Gerraty } 1065fff9558SSimon J. Gerraty /* collapse any trailing ..[/] */ 1075fff9558SSimon J. Gerraty n = 0; 10853f151f9SSimon J. Gerraty while ((cp = strrchr(nfip->fi_prefix, '/')) > nfip->fi_prefix) { 1095fff9558SSimon J. Gerraty if (cp[1] == '\0') { /* trailing "/" */ 1105fff9558SSimon J. Gerraty *cp = '\0'; 1115fff9558SSimon J. Gerraty continue; 1125fff9558SSimon J. Gerraty } 1135fff9558SSimon J. Gerraty if (strcmp(&cp[1], "..") == 0) { 1145fff9558SSimon J. Gerraty n++; 1155fff9558SSimon J. Gerraty *cp = '\0'; 1165fff9558SSimon J. Gerraty continue; 1175fff9558SSimon J. Gerraty } 1185fff9558SSimon J. Gerraty if (n > 0) { 1195fff9558SSimon J. Gerraty n--; 1205fff9558SSimon J. Gerraty *cp = '\0'; 1215fff9558SSimon J. Gerraty } 1225fff9558SSimon J. Gerraty if (n == 0) 1235fff9558SSimon J. Gerraty break; 1245fff9558SSimon J. Gerraty } 125*66655411SSimon J. Gerraty nfip->fi_dev = stp->st_dev; 1265fff9558SSimon J. Gerraty #ifdef UNIT_TEST 1275fff9558SSimon J. Gerraty nfip->fi_dev = 0; 1285fff9558SSimon J. Gerraty #endif 1295fff9558SSimon J. Gerraty nfip->fi_data = data; 1305fff9558SSimon J. Gerraty nfip->fi_prefix_len = strlen(nfip->fi_prefix); 1315fff9558SSimon J. Gerraty if (skip) { 1325fff9558SSimon J. Gerraty nfip->fi_skip_len = strlen(skip); 1335fff9558SSimon J. Gerraty if (nfip->fi_skip_len) 1345fff9558SSimon J. Gerraty nfip->fi_skip = strdup(skip); 1355fff9558SSimon J. Gerraty else 1365fff9558SSimon J. Gerraty nfip->fi_skip = NULL; 1375fff9558SSimon J. Gerraty } else { 1385fff9558SSimon J. Gerraty nfip->fi_skip = NULL; 1395fff9558SSimon J. Gerraty nfip->fi_skip_len = 0; 1405fff9558SSimon J. Gerraty } 1415fff9558SSimon J. Gerraty 1425fff9558SSimon J. Gerraty if (LIST_EMPTY(&fi_list)) { 1435fff9558SSimon J. Gerraty LIST_INSERT_HEAD(&fi_list, nfip, entries); 1445fff9558SSimon J. Gerraty DEBUG_PRINTF(4, ("inserted %zu %s at head\n", 1455fff9558SSimon J. Gerraty nfip->fi_prefix_len, nfip->fi_prefix)); 1465fff9558SSimon J. Gerraty return; 1475fff9558SSimon J. Gerraty } 1485fff9558SSimon J. Gerraty LIST_FOREACH(fip, &fi_list, entries) { 1495fff9558SSimon J. Gerraty if (nfip->fi_prefix_len >= fip->fi_prefix_len) { 1505fff9558SSimon J. Gerraty LIST_INSERT_BEFORE(fip, nfip, entries); 1515fff9558SSimon J. Gerraty DEBUG_PRINTF(4, ("inserted %zu %s before %zu %s\n", 1525fff9558SSimon J. Gerraty nfip->fi_prefix_len, nfip->fi_prefix, 1535fff9558SSimon J. Gerraty fip->fi_prefix_len, fip->fi_prefix)); 1545fff9558SSimon J. Gerraty return; 1555fff9558SSimon J. Gerraty } 1565fff9558SSimon J. Gerraty lfip = fip; 1575fff9558SSimon J. Gerraty } 1585fff9558SSimon J. Gerraty LIST_INSERT_AFTER(lfip, nfip, entries); 1595fff9558SSimon J. Gerraty DEBUG_PRINTF(4, ("inserted %zu %s after %zu %s\n", 1605fff9558SSimon J. Gerraty nfip->fi_prefix_len, nfip->fi_prefix, 1615fff9558SSimon J. Gerraty lfip->fi_prefix_len, lfip->fi_prefix)); 1625fff9558SSimon J. Gerraty } 1635fff9558SSimon J. Gerraty 1645fff9558SSimon J. Gerraty #ifdef MANIFEST_SKIP_MAYBE 1655fff9558SSimon J. Gerraty /* 1665fff9558SSimon J. Gerraty * Deal with old incompatible boot/manifest 1675fff9558SSimon J. Gerraty * if fp[-1] is '/' and start of entry matches 1685fff9558SSimon J. Gerraty * MANIFEST_SKIP_MAYBE, we want it. 1695fff9558SSimon J. Gerraty */ 1705fff9558SSimon J. Gerraty static char * 1715fff9558SSimon J. Gerraty maybe_skip(char *fp, struct fingerprint_info *fip, size_t *nplenp) 1725fff9558SSimon J. Gerraty { 1735fff9558SSimon J. Gerraty char *tp; 1745fff9558SSimon J. Gerraty 1755fff9558SSimon J. Gerraty tp = fp - sizeof(MANIFEST_SKIP_MAYBE); 1765fff9558SSimon J. Gerraty 1775fff9558SSimon J. Gerraty if (tp >= fip->fi_data) { 1785fff9558SSimon J. Gerraty DEBUG_PRINTF(3, ("maybe: %.48s\n", tp)); 1795fff9558SSimon J. Gerraty if ((tp == fip->fi_data || tp[-1] == '\n') && 1805fff9558SSimon J. Gerraty strncmp(tp, MANIFEST_SKIP_MAYBE, 1815fff9558SSimon J. Gerraty sizeof(MANIFEST_SKIP_MAYBE) - 1) == 0) { 1825fff9558SSimon J. Gerraty fp = tp; 1835fff9558SSimon J. Gerraty *nplenp += sizeof(MANIFEST_SKIP_MAYBE); 1845fff9558SSimon J. Gerraty } 1855fff9558SSimon J. Gerraty } 1865fff9558SSimon J. Gerraty return (fp); 1875fff9558SSimon J. Gerraty } 1885fff9558SSimon J. Gerraty #endif 1895fff9558SSimon J. Gerraty 1905fff9558SSimon J. Gerraty char * 1915fff9558SSimon J. Gerraty fingerprint_info_lookup(int fd, const char *path) 1925fff9558SSimon J. Gerraty { 1935fff9558SSimon J. Gerraty char pbuf[MAXPATHLEN+1]; 1945fff9558SSimon J. Gerraty char nbuf[MAXPATHLEN+1]; 1955fff9558SSimon J. Gerraty struct stat st; 1965fff9558SSimon J. Gerraty struct fingerprint_info *fip; 1975fff9558SSimon J. Gerraty char *cp, *ep, *fp, *np; 1985fff9558SSimon J. Gerraty const char *prefix; 1995fff9558SSimon J. Gerraty size_t n, plen, nlen, nplen; 2005fff9558SSimon J. Gerraty dev_t dev = 0; 2015fff9558SSimon J. Gerraty 2025fff9558SSimon J. Gerraty fingerprint_info_init(); 2035fff9558SSimon J. Gerraty 2045fff9558SSimon J. Gerraty n = strlcpy(pbuf, path, sizeof(pbuf)); 2055fff9558SSimon J. Gerraty if (n >= sizeof(pbuf)) 2065fff9558SSimon J. Gerraty return (NULL); 2075fff9558SSimon J. Gerraty if (fstat(fd, &st) == 0) 2085fff9558SSimon J. Gerraty dev = st.st_dev; 209*66655411SSimon J. Gerraty #ifdef UNIT_TEST 210*66655411SSimon J. Gerraty dev = 0; 2115fff9558SSimon J. Gerraty #endif 2125fff9558SSimon J. Gerraty /* 2135fff9558SSimon J. Gerraty * get the first entry - it will have longest prefix 2145fff9558SSimon J. Gerraty * so we can can work out how to initially split path 2155fff9558SSimon J. Gerraty */ 2165fff9558SSimon J. Gerraty fip = LIST_FIRST(&fi_list); 2175fff9558SSimon J. Gerraty if (!fip) 2185fff9558SSimon J. Gerraty return (NULL); 2195fff9558SSimon J. Gerraty prefix = pbuf; 2205fff9558SSimon J. Gerraty ep = NULL; 2215fff9558SSimon J. Gerraty cp = &pbuf[fip->fi_prefix_len]; 2225fff9558SSimon J. Gerraty do { 2235fff9558SSimon J. Gerraty if (ep) { 2245fff9558SSimon J. Gerraty *ep = '/'; 2255fff9558SSimon J. Gerraty cp -= 2; 2265fff9558SSimon J. Gerraty if (cp < pbuf) 2275fff9558SSimon J. Gerraty break; 2285fff9558SSimon J. Gerraty } 2295fff9558SSimon J. Gerraty nlen = plen = 0; /* keep gcc quiet */ 2305fff9558SSimon J. Gerraty if (cp > pbuf) { 2315fff9558SSimon J. Gerraty for ( ; cp >= pbuf && *cp != '/'; cp--) 2325fff9558SSimon J. Gerraty ; /* nothing */ 2335fff9558SSimon J. Gerraty if (cp > pbuf) { 2345fff9558SSimon J. Gerraty ep = cp++; 2355fff9558SSimon J. Gerraty *ep = '\0'; 2365fff9558SSimon J. Gerraty } else { 2375fff9558SSimon J. Gerraty cp = pbuf; 2385fff9558SSimon J. Gerraty } 2395fff9558SSimon J. Gerraty if (ep) { 2405fff9558SSimon J. Gerraty plen = ep - pbuf; 2415fff9558SSimon J. Gerraty nlen = n - plen - 1; 2425fff9558SSimon J. Gerraty } 2435fff9558SSimon J. Gerraty } 2445fff9558SSimon J. Gerraty if (cp == pbuf) { 2455fff9558SSimon J. Gerraty prefix = "/"; 2465fff9558SSimon J. Gerraty plen = 1; 2475fff9558SSimon J. Gerraty if (*cp == '/') { 2485fff9558SSimon J. Gerraty nlen = n - 1; 2495fff9558SSimon J. Gerraty cp++; 2505fff9558SSimon J. Gerraty } else 2515fff9558SSimon J. Gerraty nlen = n; 2525fff9558SSimon J. Gerraty ep = NULL; 2535fff9558SSimon J. Gerraty } 2545fff9558SSimon J. Gerraty 2555fff9558SSimon J. Gerraty DEBUG_PRINTF(2, ("looking for %s %zu %s\n", prefix, plen, cp)); 2565fff9558SSimon J. Gerraty 2575fff9558SSimon J. Gerraty LIST_FOREACH(fip, &fi_list, entries) { 2585fff9558SSimon J. Gerraty DEBUG_PRINTF(4, ("at %zu %s\n", 2595fff9558SSimon J. Gerraty fip->fi_prefix_len, fip->fi_prefix)); 2605fff9558SSimon J. Gerraty 2615fff9558SSimon J. Gerraty if (fip->fi_prefix_len < plen) { 2625fff9558SSimon J. Gerraty DEBUG_PRINTF(3, ("skipping prefix=%s %zu %zu\n", 2635fff9558SSimon J. Gerraty fip->fi_prefix, fip->fi_prefix_len, 2645fff9558SSimon J. Gerraty plen)); 2655fff9558SSimon J. Gerraty break; 2665fff9558SSimon J. Gerraty } 2675fff9558SSimon J. Gerraty if (fip->fi_prefix_len == plen) { 2685fff9558SSimon J. Gerraty if (fip->fi_dev != 0 && fip->fi_dev != dev) { 2695fff9558SSimon J. Gerraty DEBUG_PRINTF(3, ( 2705fff9558SSimon J. Gerraty "skipping dev=%ld != %ld\n", 2715fff9558SSimon J. Gerraty (long)fip->fi_dev, 2725fff9558SSimon J. Gerraty (long)dev)); 2735fff9558SSimon J. Gerraty continue; 2745fff9558SSimon J. Gerraty } 2755fff9558SSimon J. Gerraty if (strcmp(prefix, fip->fi_prefix)) { 2765fff9558SSimon J. Gerraty DEBUG_PRINTF(3, ( 2775fff9558SSimon J. Gerraty "skipping prefix=%s\n", 2785fff9558SSimon J. Gerraty fip->fi_prefix)); 2795fff9558SSimon J. Gerraty continue; 2805fff9558SSimon J. Gerraty } 2815fff9558SSimon J. Gerraty DEBUG_PRINTF(3, ("checking prefix=%s\n", 2825fff9558SSimon J. Gerraty fip->fi_prefix)); 2835fff9558SSimon J. Gerraty if (fip->fi_skip_len) { 2845fff9558SSimon J. Gerraty np = nbuf; 2855fff9558SSimon J. Gerraty nplen = snprintf(nbuf, sizeof(nbuf), 2865fff9558SSimon J. Gerraty "%s/%s", 2875fff9558SSimon J. Gerraty fip->fi_skip, cp); 2885fff9558SSimon J. Gerraty nplen = MIN(nplen, sizeof(nbuf) - 1); 2895fff9558SSimon J. Gerraty } else { 2905fff9558SSimon J. Gerraty np = cp; 2915fff9558SSimon J. Gerraty nplen = nlen; 2925fff9558SSimon J. Gerraty } 2935fff9558SSimon J. Gerraty DEBUG_PRINTF(3, ("lookup: '%s'\n", np)); 2945fff9558SSimon J. Gerraty if (!(fp = strstr(fip->fi_data, np))) 2955fff9558SSimon J. Gerraty continue; 2965fff9558SSimon J. Gerraty #ifdef MANIFEST_SKIP_MAYBE 2975fff9558SSimon J. Gerraty if (fip->fi_skip_len == 0 && 2985fff9558SSimon J. Gerraty fp > fip->fi_data && fp[-1] == '/') { 2995fff9558SSimon J. Gerraty fp = maybe_skip(fp, fip, &nplen); 3005fff9558SSimon J. Gerraty } 3015fff9558SSimon J. Gerraty #endif 3025fff9558SSimon J. Gerraty /* 3035fff9558SSimon J. Gerraty * when we find a match: 3045fff9558SSimon J. Gerraty * fp[nplen] will be space and 3055fff9558SSimon J. Gerraty * fp will be fip->fi_data or 3065fff9558SSimon J. Gerraty * fp[-1] will be \n 3075fff9558SSimon J. Gerraty */ 3085fff9558SSimon J. Gerraty if (!((fp == fip->fi_data || fp[-1] == '\n') && 3095fff9558SSimon J. Gerraty fp[nplen] == ' ')) { 3105fff9558SSimon J. Gerraty do { 3115fff9558SSimon J. Gerraty fp++; 3125fff9558SSimon J. Gerraty fp = strstr(fp, np); 3135fff9558SSimon J. Gerraty if (fp) { 3145fff9558SSimon J. Gerraty #ifdef MANIFEST_SKIP_MAYBE 3155fff9558SSimon J. Gerraty if (fip->fi_skip_len == 0 && 3165fff9558SSimon J. Gerraty fp > fip->fi_data && 3175fff9558SSimon J. Gerraty fp[-1] == '/') { 3185fff9558SSimon J. Gerraty fp = maybe_skip(fp, fip, &nplen); 3195fff9558SSimon J. Gerraty } 3205fff9558SSimon J. Gerraty #endif 3215fff9558SSimon J. Gerraty DEBUG_PRINTF(3, 3225fff9558SSimon J. Gerraty ("fp[-1]=%#x fp[%zu]=%#x fp=%.78s\n", 3235fff9558SSimon J. Gerraty fp[-1], nplen, 3245fff9558SSimon J. Gerraty fp[nplen], 3255fff9558SSimon J. Gerraty fp)); 3265fff9558SSimon J. Gerraty } 3275fff9558SSimon J. Gerraty } while (fp != NULL && 3285fff9558SSimon J. Gerraty !(fp[-1] == '\n' && 3295fff9558SSimon J. Gerraty fp[nplen] == ' ')); 3305fff9558SSimon J. Gerraty if (!fp) 3315fff9558SSimon J. Gerraty continue; 3325fff9558SSimon J. Gerraty } 3335fff9558SSimon J. Gerraty DEBUG_PRINTF(2, ("found %.78s\n", fp)); 3345fff9558SSimon J. Gerraty /* we have a match! */ 3355fff9558SSimon J. Gerraty for (cp = &fp[nplen]; *cp == ' '; cp++) 3365fff9558SSimon J. Gerraty ; /* nothing */ 3375fff9558SSimon J. Gerraty return (cp); 3385fff9558SSimon J. Gerraty } else { 3395fff9558SSimon J. Gerraty DEBUG_PRINTF(3, 3405fff9558SSimon J. Gerraty ("Ignoring prefix=%s\n", fip->fi_prefix)); 3415fff9558SSimon J. Gerraty } 3425fff9558SSimon J. Gerraty } 3435fff9558SSimon J. Gerraty } while (cp > &pbuf[1]); 3445fff9558SSimon J. Gerraty 3455fff9558SSimon J. Gerraty return (NULL); 3465fff9558SSimon J. Gerraty } 3475fff9558SSimon J. Gerraty 3485fff9558SSimon J. Gerraty static int 3495fff9558SSimon J. Gerraty verify_fingerprint(int fd, const char *path, const char *cp, off_t off) 3505fff9558SSimon J. Gerraty { 3515fff9558SSimon J. Gerraty unsigned char buf[PAGE_SIZE]; 3525fff9558SSimon J. Gerraty const br_hash_class *md; 3535fff9558SSimon J. Gerraty br_hash_compat_context mctx; 3545fff9558SSimon J. Gerraty size_t hlen; 3555fff9558SSimon J. Gerraty int n; 3565fff9558SSimon J. Gerraty 35764ca9a7fSSimon J. Gerraty if (strncmp(cp, "no_hash", 7) == 0) { 35864ca9a7fSSimon J. Gerraty return (VE_FINGERPRINT_IGNORE); 35964ca9a7fSSimon J. Gerraty } else if (strncmp(cp, "sha256=", 7) == 0) { 3605fff9558SSimon J. Gerraty md = &br_sha256_vtable; 3615fff9558SSimon J. Gerraty hlen = br_sha256_SIZE; 3625fff9558SSimon J. Gerraty cp += 7; 3635fff9558SSimon J. Gerraty #ifdef VE_SHA1_SUPPORT 3645fff9558SSimon J. Gerraty } else if (strncmp(cp, "sha1=", 5) == 0) { 3655fff9558SSimon J. Gerraty md = &br_sha1_vtable; 3665fff9558SSimon J. Gerraty hlen = br_sha1_SIZE; 3675fff9558SSimon J. Gerraty cp += 5; 3685fff9558SSimon J. Gerraty #endif 3695fff9558SSimon J. Gerraty #ifdef VE_SHA384_SUPPORT 3705fff9558SSimon J. Gerraty } else if (strncmp(cp, "sha384=", 7) == 0) { 3715fff9558SSimon J. Gerraty md = &br_sha384_vtable; 3725fff9558SSimon J. Gerraty hlen = br_sha384_SIZE; 3735fff9558SSimon J. Gerraty cp += 7; 3745fff9558SSimon J. Gerraty #endif 3755fff9558SSimon J. Gerraty #ifdef VE_SHA512_SUPPORT 3765fff9558SSimon J. Gerraty } else if (strncmp(cp, "sha512=", 7) == 0) { 3775fff9558SSimon J. Gerraty md = &br_sha512_vtable; 3785fff9558SSimon J. Gerraty hlen = br_sha512_SIZE; 3795fff9558SSimon J. Gerraty cp += 7; 3805fff9558SSimon J. Gerraty #endif 3815fff9558SSimon J. Gerraty } else { 3825fff9558SSimon J. Gerraty ve_error_set("%s: no supported fingerprint", path); 3835fff9558SSimon J. Gerraty return (VE_FINGERPRINT_UNKNOWN); 3845fff9558SSimon J. Gerraty } 3855fff9558SSimon J. Gerraty 3865fff9558SSimon J. Gerraty md->init(&mctx.vtable); 3875fff9558SSimon J. Gerraty if (off) 3885fff9558SSimon J. Gerraty lseek(fd, 0, SEEK_SET); 3895fff9558SSimon J. Gerraty do { 3905fff9558SSimon J. Gerraty n = read(fd, buf, sizeof(buf)); 3915fff9558SSimon J. Gerraty if (n < 0) 3925fff9558SSimon J. Gerraty return (n); 3935fff9558SSimon J. Gerraty if (n > 0) 3945fff9558SSimon J. Gerraty md->update(&mctx.vtable, buf, n); 3955fff9558SSimon J. Gerraty } while (n > 0); 3965fff9558SSimon J. Gerraty lseek(fd, off, SEEK_SET); 3975fff9558SSimon J. Gerraty return (ve_check_hash(&mctx, md, path, cp, hlen)); 3985fff9558SSimon J. Gerraty } 3995fff9558SSimon J. Gerraty 4005fff9558SSimon J. Gerraty 4015fff9558SSimon J. Gerraty /** 4025fff9558SSimon J. Gerraty * @brief 4035fff9558SSimon J. Gerraty * verify an open file 4045fff9558SSimon J. Gerraty * 4055fff9558SSimon J. Gerraty * @param[in] fd 4065fff9558SSimon J. Gerraty * open descriptor 4075fff9558SSimon J. Gerraty * 4085fff9558SSimon J. Gerraty * @param[in] path 4095fff9558SSimon J. Gerraty * pathname to open 4105fff9558SSimon J. Gerraty * 4115fff9558SSimon J. Gerraty * @param[in] off 4125fff9558SSimon J. Gerraty * current offset 4135fff9558SSimon J. Gerraty * 4145fff9558SSimon J. Gerraty * @return 0, VE_FINGERPRINT_OK or VE_FINGERPRINT_NONE, VE_FINGERPRINT_WRONG 4155fff9558SSimon J. Gerraty */ 4165fff9558SSimon J. Gerraty int 4175fff9558SSimon J. Gerraty verify_fd(int fd, const char *path, off_t off, struct stat *stp) 4185fff9558SSimon J. Gerraty { 4195fff9558SSimon J. Gerraty struct stat st; 4205fff9558SSimon J. Gerraty char *cp; 4215fff9558SSimon J. Gerraty int rc; 4225fff9558SSimon J. Gerraty 4235fff9558SSimon J. Gerraty if (!stp) { 4245fff9558SSimon J. Gerraty if (fstat(fd, &st) == 0) 4255fff9558SSimon J. Gerraty stp = &st; 4265fff9558SSimon J. Gerraty } 4275fff9558SSimon J. Gerraty if (stp && !S_ISREG(stp->st_mode)) 4285fff9558SSimon J. Gerraty return (0); /* not relevant */ 4295fff9558SSimon J. Gerraty cp = fingerprint_info_lookup(fd, path); 4305fff9558SSimon J. Gerraty if (!cp) { 4315fff9558SSimon J. Gerraty ve_error_set("%s: no entry", path); 4325fff9558SSimon J. Gerraty return (VE_FINGERPRINT_NONE); 4335fff9558SSimon J. Gerraty } 4345fff9558SSimon J. Gerraty rc = verify_fingerprint(fd, path, cp, off); 4355fff9558SSimon J. Gerraty switch (rc) { 4365fff9558SSimon J. Gerraty case VE_FINGERPRINT_OK: 43764ca9a7fSSimon J. Gerraty case VE_FINGERPRINT_IGNORE: 4385fff9558SSimon J. Gerraty case VE_FINGERPRINT_UNKNOWN: 4395fff9558SSimon J. Gerraty return (rc); 4405fff9558SSimon J. Gerraty default: 4415fff9558SSimon J. Gerraty return (VE_FINGERPRINT_WRONG); 4425fff9558SSimon J. Gerraty } 4435fff9558SSimon J. Gerraty } 4445fff9558SSimon J. Gerraty 4455fff9558SSimon J. Gerraty /** 4465fff9558SSimon J. Gerraty * @brief 4475fff9558SSimon J. Gerraty * open a file if it can be verified 4485fff9558SSimon J. Gerraty * 4495fff9558SSimon J. Gerraty * @param[in] path 4505fff9558SSimon J. Gerraty * pathname to open 4515fff9558SSimon J. Gerraty * 4525fff9558SSimon J. Gerraty * @param[in] flags 4535fff9558SSimon J. Gerraty * flags for open 4545fff9558SSimon J. Gerraty * 4555fff9558SSimon J. Gerraty * @return fd or VE_FINGERPRINT_NONE, VE_FINGERPRINT_WRONG 4565fff9558SSimon J. Gerraty */ 4575fff9558SSimon J. Gerraty int 4585fff9558SSimon J. Gerraty verify_open(const char *path, int flags) 4595fff9558SSimon J. Gerraty { 4605fff9558SSimon J. Gerraty int fd; 4615fff9558SSimon J. Gerraty int rc; 4625fff9558SSimon J. Gerraty 4635fff9558SSimon J. Gerraty if ((fd = open(path, flags)) >= 0) { 4645fff9558SSimon J. Gerraty if ((rc = verify_fd(fd, path, 0, NULL)) < 0) { 4655fff9558SSimon J. Gerraty close(fd); 4665fff9558SSimon J. Gerraty fd = rc; 4675fff9558SSimon J. Gerraty } 4685fff9558SSimon J. Gerraty } 4695fff9558SSimon J. Gerraty return (fd); 4705fff9558SSimon J. Gerraty } 471