15fff9558SSimon J. Gerraty /*- 25fff9558SSimon J. Gerraty * Copyright (c) 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 285fff9558SSimon J. Gerraty #ifndef _STANDALONE 295fff9558SSimon J. Gerraty /* Avoid unwanted userlandish components */ 305fff9558SSimon J. Gerraty #define _KERNEL 315fff9558SSimon J. Gerraty #include <sys/errno.h> 325fff9558SSimon J. Gerraty #undef _KERNEL 335fff9558SSimon J. Gerraty #endif 345fff9558SSimon J. Gerraty 35*66655411SSimon J. Gerraty #ifdef VECTX_DEBUG 36*66655411SSimon J. Gerraty static int vectx_debug = VECTX_DEBUG; 37*66655411SSimon J. Gerraty # define DEBUG_PRINTF(n, x) if (vectx_debug >= n) printf x 38*66655411SSimon J. Gerraty #endif 39*66655411SSimon J. Gerraty 405fff9558SSimon J. Gerraty #include "libsecureboot-priv.h" 41afc571b1SSimon J. Gerraty #include <verify_file.h> 425fff9558SSimon J. Gerraty 435fff9558SSimon J. Gerraty /** 445fff9558SSimon J. Gerraty * @file vectx.c 455fff9558SSimon J. Gerraty * @brief api to verify file while reading 465fff9558SSimon J. Gerraty * 475fff9558SSimon J. Gerraty * This API allows the hash of a file to be computed as it is read. 485fff9558SSimon J. Gerraty * Key to this is seeking by reading. 495fff9558SSimon J. Gerraty * 505fff9558SSimon J. Gerraty * On close an indication of the verification result is returned. 515fff9558SSimon J. Gerraty */ 525fff9558SSimon J. Gerraty 535fff9558SSimon J. Gerraty struct vectx { 545fff9558SSimon J. Gerraty br_hash_compat_context vec_ctx; /* hash ctx */ 555fff9558SSimon J. Gerraty const br_hash_class *vec_md; /* hash method */ 565fff9558SSimon J. Gerraty const char *vec_path; /* path we are verifying */ 575fff9558SSimon J. Gerraty const char *vec_want; /* hash value we want */ 585fff9558SSimon J. Gerraty off_t vec_off; /* current offset */ 59afc571b1SSimon J. Gerraty off_t vec_hashed; /* where we have hashed to */ 60*66655411SSimon J. Gerraty off_t vec_size; /* size of path */ 615fff9558SSimon J. Gerraty size_t vec_hashsz; /* size of hash */ 625fff9558SSimon J. Gerraty int vec_fd; /* file descriptor */ 635fff9558SSimon J. Gerraty int vec_status; /* verification status */ 64*66655411SSimon J. Gerraty int vec_closing; /* we are closing */ 655fff9558SSimon J. Gerraty }; 665fff9558SSimon J. Gerraty 67afc571b1SSimon J. Gerraty 685fff9558SSimon J. Gerraty /** 695fff9558SSimon J. Gerraty * @brief 705fff9558SSimon J. Gerraty * verify an open file as we read it 715fff9558SSimon J. Gerraty * 725fff9558SSimon J. Gerraty * If the file has no fingerprint to match, we will still return a 735fff9558SSimon J. Gerraty * verification context containing little more than the file 745fff9558SSimon J. Gerraty * descriptor, and an error code in @c error. 755fff9558SSimon J. Gerraty * 765fff9558SSimon J. Gerraty * @param[in] fd 775fff9558SSimon J. Gerraty * open descriptor 785fff9558SSimon J. Gerraty * 795fff9558SSimon J. Gerraty * @param[in] path 805fff9558SSimon J. Gerraty * pathname to open 815fff9558SSimon J. Gerraty * 825fff9558SSimon J. Gerraty * @param[in] off 835fff9558SSimon J. Gerraty * current offset 845fff9558SSimon J. Gerraty * 855fff9558SSimon J. Gerraty * @param[in] stp 865fff9558SSimon J. Gerraty * pointer to struct stat 875fff9558SSimon J. Gerraty * 885fff9558SSimon J. Gerraty * @param[out] error 895fff9558SSimon J. Gerraty * @li 0 all is good 905fff9558SSimon J. Gerraty * @li ENOMEM out of memory 915fff9558SSimon J. Gerraty * @li VE_FINGERPRINT_NONE no entry found 925fff9558SSimon J. Gerraty * @li VE_FINGERPRINT_UNKNOWN no fingerprint in entry 935fff9558SSimon J. Gerraty * 945fff9558SSimon J. Gerraty * @return ctx or NULL on error. 955fff9558SSimon J. Gerraty * NULL is only returned for non-files or out-of-memory. 965fff9558SSimon J. Gerraty */ 975fff9558SSimon J. Gerraty struct vectx * 98afc571b1SSimon J. Gerraty vectx_open(int fd, const char *path, off_t off, struct stat *stp, 99afc571b1SSimon J. Gerraty int *error, const char *caller) 1005fff9558SSimon J. Gerraty { 1015fff9558SSimon J. Gerraty struct vectx *ctx; 1025fff9558SSimon J. Gerraty struct stat st; 1035fff9558SSimon J. Gerraty size_t hashsz; 1045fff9558SSimon J. Gerraty char *cp; 105afc571b1SSimon J. Gerraty int rc; 1065fff9558SSimon J. Gerraty 107afc571b1SSimon J. Gerraty if (!stp) 1085fff9558SSimon J. Gerraty stp = &st; 1095fff9558SSimon J. Gerraty 110afc571b1SSimon J. Gerraty rc = verify_prep(fd, path, off, stp, __func__); 111afc571b1SSimon J. Gerraty 112afc571b1SSimon J. Gerraty DEBUG_PRINTF(2, 11353f151f9SSimon J. Gerraty ("vectx_open: caller=%s,fd=%d,name='%s',prep_rc=%d\n", 11453f151f9SSimon J. Gerraty caller, fd, path, rc)); 115afc571b1SSimon J. Gerraty 116afc571b1SSimon J. Gerraty switch (rc) { 117afc571b1SSimon J. Gerraty case VE_FINGERPRINT_NONE: 118afc571b1SSimon J. Gerraty case VE_FINGERPRINT_UNKNOWN: 119afc571b1SSimon J. Gerraty case VE_FINGERPRINT_WRONG: 120afc571b1SSimon J. Gerraty *error = rc; 1215fff9558SSimon J. Gerraty return (NULL); 1225fff9558SSimon J. Gerraty } 1235fff9558SSimon J. Gerraty ctx = malloc(sizeof(struct vectx)); 1245fff9558SSimon J. Gerraty if (!ctx) 1255fff9558SSimon J. Gerraty goto enomem; 1265fff9558SSimon J. Gerraty ctx->vec_fd = fd; 1275fff9558SSimon J. Gerraty ctx->vec_path = path; 1285fff9558SSimon J. Gerraty ctx->vec_size = stp->st_size; 1295fff9558SSimon J. Gerraty ctx->vec_off = 0; 130afc571b1SSimon J. Gerraty ctx->vec_hashed = 0; 1315fff9558SSimon J. Gerraty ctx->vec_want = NULL; 1325fff9558SSimon J. Gerraty ctx->vec_status = 0; 133afc571b1SSimon J. Gerraty ctx->vec_hashsz = hashsz = 0; 134*66655411SSimon J. Gerraty ctx->vec_closing = 0; 1355fff9558SSimon J. Gerraty 136afc571b1SSimon J. Gerraty if (rc == 0) { 137afc571b1SSimon J. Gerraty /* we are not verifying this */ 138afc571b1SSimon J. Gerraty *error = 0; 139afc571b1SSimon J. Gerraty return (ctx); 140afc571b1SSimon J. Gerraty } 1415fff9558SSimon J. Gerraty cp = fingerprint_info_lookup(fd, path); 1425fff9558SSimon J. Gerraty if (!cp) { 1435fff9558SSimon J. Gerraty ctx->vec_status = VE_FINGERPRINT_NONE; 1445fff9558SSimon J. Gerraty ve_error_set("%s: no entry", path); 1455fff9558SSimon J. Gerraty } else { 14664ca9a7fSSimon J. Gerraty if (strncmp(cp, "no_hash", 7) == 0) { 14764ca9a7fSSimon J. Gerraty ctx->vec_status = VE_FINGERPRINT_IGNORE; 14864ca9a7fSSimon J. Gerraty hashsz = 0; 14964ca9a7fSSimon J. Gerraty } else if (strncmp(cp, "sha256=", 7) == 0) { 1505fff9558SSimon J. Gerraty ctx->vec_md = &br_sha256_vtable; 1515fff9558SSimon J. Gerraty hashsz = br_sha256_SIZE; 1525fff9558SSimon J. Gerraty cp += 7; 1535fff9558SSimon J. Gerraty #ifdef VE_SHA1_SUPPORT 1545fff9558SSimon J. Gerraty } else if (strncmp(cp, "sha1=", 5) == 0) { 1555fff9558SSimon J. Gerraty ctx->vec_md = &br_sha1_vtable; 1565fff9558SSimon J. Gerraty hashsz = br_sha1_SIZE; 1575fff9558SSimon J. Gerraty cp += 5; 1585fff9558SSimon J. Gerraty #endif 1595fff9558SSimon J. Gerraty #ifdef VE_SHA384_SUPPORT 1605fff9558SSimon J. Gerraty } else if (strncmp(cp, "sha384=", 7) == 0) { 1615fff9558SSimon J. Gerraty ctx->vec_md = &br_sha384_vtable; 1625fff9558SSimon J. Gerraty hashsz = br_sha384_SIZE; 1635fff9558SSimon J. Gerraty cp += 7; 1645fff9558SSimon J. Gerraty #endif 1655fff9558SSimon J. Gerraty #ifdef VE_SHA512_SUPPORT 1665fff9558SSimon J. Gerraty } else if (strncmp(cp, "sha512=", 7) == 0) { 1675fff9558SSimon J. Gerraty ctx->vec_md = &br_sha512_vtable; 1685fff9558SSimon J. Gerraty hashsz = br_sha512_SIZE; 1695fff9558SSimon J. Gerraty cp += 7; 1705fff9558SSimon J. Gerraty #endif 1715fff9558SSimon J. Gerraty } else { 1725fff9558SSimon J. Gerraty ctx->vec_status = VE_FINGERPRINT_UNKNOWN; 1735fff9558SSimon J. Gerraty ve_error_set("%s: no supported fingerprint", path); 1745fff9558SSimon J. Gerraty } 1755fff9558SSimon J. Gerraty } 1765fff9558SSimon J. Gerraty *error = ctx->vec_status; 1775fff9558SSimon J. Gerraty ctx->vec_hashsz = hashsz; 1785fff9558SSimon J. Gerraty ctx->vec_want = cp; 17964ca9a7fSSimon J. Gerraty if (hashsz > 0) { 1805fff9558SSimon J. Gerraty ctx->vec_md->init(&ctx->vec_ctx.vtable); 1815fff9558SSimon J. Gerraty 18264ca9a7fSSimon J. Gerraty if (off > 0) { 1835fff9558SSimon J. Gerraty lseek(fd, 0, SEEK_SET); 1845fff9558SSimon J. Gerraty vectx_lseek(ctx, off, SEEK_SET); 1855fff9558SSimon J. Gerraty } 18664ca9a7fSSimon J. Gerraty } 187afc571b1SSimon J. Gerraty DEBUG_PRINTF(2, 188afc571b1SSimon J. Gerraty ("vectx_open: caller=%s,name='%s',hashsz=%lu,status=%d\n", 189afc571b1SSimon J. Gerraty caller, path, (unsigned long)ctx->vec_hashsz, 190afc571b1SSimon J. Gerraty ctx->vec_status)); 1915fff9558SSimon J. Gerraty return (ctx); 1925fff9558SSimon J. Gerraty 1935fff9558SSimon J. Gerraty enomem: /* unlikely */ 1945fff9558SSimon J. Gerraty *error = ENOMEM; 1955fff9558SSimon J. Gerraty free(ctx); 1965fff9558SSimon J. Gerraty return (NULL); 1975fff9558SSimon J. Gerraty } 1985fff9558SSimon J. Gerraty 1995fff9558SSimon J. Gerraty /** 2005fff9558SSimon J. Gerraty * @brief 2015fff9558SSimon J. Gerraty * read bytes from file and update hash 2025fff9558SSimon J. Gerraty * 2035fff9558SSimon J. Gerraty * It is critical that all file I/O comes through here. 2045fff9558SSimon J. Gerraty * We keep track of current offset. 205afc571b1SSimon J. Gerraty * We also track what offset we have hashed to, 206afc571b1SSimon J. Gerraty * so we won't replay data if we seek backwards. 2075fff9558SSimon J. Gerraty * 2085fff9558SSimon J. Gerraty * @param[in] pctx 2095fff9558SSimon J. Gerraty * pointer to ctx 2105fff9558SSimon J. Gerraty * 2115fff9558SSimon J. Gerraty * @param[in] buf 2125fff9558SSimon J. Gerraty * 2135fff9558SSimon J. Gerraty * @param[in] nbytes 2145fff9558SSimon J. Gerraty * 2155fff9558SSimon J. Gerraty * @return bytes read or error. 2165fff9558SSimon J. Gerraty */ 2175fff9558SSimon J. Gerraty ssize_t 2185fff9558SSimon J. Gerraty vectx_read(struct vectx *ctx, void *buf, size_t nbytes) 2195fff9558SSimon J. Gerraty { 2205fff9558SSimon J. Gerraty unsigned char *bp = buf; 221723f9041SSimon J. Gerraty int d; 2225fff9558SSimon J. Gerraty int n; 223afc571b1SSimon J. Gerraty int delta; 224afc571b1SSimon J. Gerraty int x; 2255fff9558SSimon J. Gerraty size_t off; 2265fff9558SSimon J. Gerraty 2275fff9558SSimon J. Gerraty if (ctx->vec_hashsz == 0) /* nothing to do */ 2285fff9558SSimon J. Gerraty return (read(ctx->vec_fd, buf, nbytes)); 2295fff9558SSimon J. Gerraty 2305fff9558SSimon J. Gerraty off = 0; 2315fff9558SSimon J. Gerraty do { 232723f9041SSimon J. Gerraty /* 233723f9041SSimon J. Gerraty * Do this in reasonable chunks so 234723f9041SSimon J. Gerraty * we don't timeout if doing tftp 235723f9041SSimon J. Gerraty */ 236723f9041SSimon J. Gerraty x = nbytes - off; 237723f9041SSimon J. Gerraty x = MIN(PAGE_SIZE, x); 238723f9041SSimon J. Gerraty d = n = read(ctx->vec_fd, &bp[off], x); 239*66655411SSimon J. Gerraty if (ctx->vec_closing && n < x) { 240*66655411SSimon J. Gerraty DEBUG_PRINTF(3, 241*66655411SSimon J. Gerraty ("%s: read %d off=%ld hashed=%ld size=%ld\n", 242*66655411SSimon J. Gerraty __func__, n, (long)ctx->vec_off, 243*66655411SSimon J. Gerraty (long)ctx->vec_hashed, (long)ctx->vec_size)); 244*66655411SSimon J. Gerraty } 245723f9041SSimon J. Gerraty if (n < 0) { 2465fff9558SSimon J. Gerraty return (n); 247723f9041SSimon J. Gerraty } 248723f9041SSimon J. Gerraty if (d > 0) { 249afc571b1SSimon J. Gerraty /* we may have seeked backwards! */ 250afc571b1SSimon J. Gerraty delta = ctx->vec_hashed - ctx->vec_off; 251afc571b1SSimon J. Gerraty if (delta > 0) { 252723f9041SSimon J. Gerraty x = MIN(delta, d); 253afc571b1SSimon J. Gerraty off += x; 254723f9041SSimon J. Gerraty d -= x; 255afc571b1SSimon J. Gerraty ctx->vec_off += x; 256afc571b1SSimon J. Gerraty } 257723f9041SSimon J. Gerraty if (d > 0) { 258*66655411SSimon J. Gerraty if (ctx->vec_closing && d < PAGE_SIZE) { 259*66655411SSimon J. Gerraty DEBUG_PRINTF(3, 260*66655411SSimon J. Gerraty ("%s: update %ld + %d\n", 261*66655411SSimon J. Gerraty __func__, 262*66655411SSimon J. Gerraty (long)ctx->vec_hashed, d)); 263*66655411SSimon J. Gerraty } 264723f9041SSimon J. Gerraty ctx->vec_md->update(&ctx->vec_ctx.vtable, &bp[off], d); 265723f9041SSimon J. Gerraty off += d; 266723f9041SSimon J. Gerraty ctx->vec_off += d; 267723f9041SSimon J. Gerraty ctx->vec_hashed += d; 268afc571b1SSimon J. Gerraty } 2695fff9558SSimon J. Gerraty } 2705fff9558SSimon J. Gerraty } while (n > 0 && off < nbytes); 2715fff9558SSimon J. Gerraty return (off); 2725fff9558SSimon J. Gerraty } 2735fff9558SSimon J. Gerraty 2745fff9558SSimon J. Gerraty /** 2755fff9558SSimon J. Gerraty * @brief 2765fff9558SSimon J. Gerraty * vectx equivalent of lseek 2775fff9558SSimon J. Gerraty * 278afc571b1SSimon J. Gerraty * When seeking forwards we actually call vectx_read 2795fff9558SSimon J. Gerraty * to reach the desired offset. 2805fff9558SSimon J. Gerraty * 281afc571b1SSimon J. Gerraty * We support seeking backwards. 2825fff9558SSimon J. Gerraty * 2835fff9558SSimon J. Gerraty * @param[in] pctx 2845fff9558SSimon J. Gerraty * pointer to ctx 2855fff9558SSimon J. Gerraty * 2865fff9558SSimon J. Gerraty * @param[in] off 2875fff9558SSimon J. Gerraty * desired offset 2885fff9558SSimon J. Gerraty * 2895fff9558SSimon J. Gerraty * @param[in] whence 290afc571b1SSimon J. Gerraty * We try to convert whence to ``SEEK_SET``. 291afc571b1SSimon J. Gerraty * We do not support ``SEEK_DATA`` or ``SEEK_HOLE``. 2925fff9558SSimon J. Gerraty * 2935fff9558SSimon J. Gerraty * @return offset or error. 2945fff9558SSimon J. Gerraty */ 2955fff9558SSimon J. Gerraty off_t 2965fff9558SSimon J. Gerraty vectx_lseek(struct vectx *ctx, off_t off, int whence) 2975fff9558SSimon J. Gerraty { 2985fff9558SSimon J. Gerraty unsigned char buf[PAGE_SIZE]; 2995fff9558SSimon J. Gerraty size_t delta; 3005fff9558SSimon J. Gerraty ssize_t n; 3015fff9558SSimon J. Gerraty 3025fff9558SSimon J. Gerraty if (ctx->vec_hashsz == 0) /* nothing to do */ 3035fff9558SSimon J. Gerraty return (lseek(ctx->vec_fd, off, whence)); 3045fff9558SSimon J. Gerraty 3055fff9558SSimon J. Gerraty /* 306afc571b1SSimon J. Gerraty * Convert whence to SEEK_SET 3075fff9558SSimon J. Gerraty */ 308*66655411SSimon J. Gerraty DEBUG_PRINTF(3, 309*66655411SSimon J. Gerraty ("%s(%s, %ld, %d)\n", __func__, ctx->vec_path, (long)off, whence)); 3105fff9558SSimon J. Gerraty if (whence == SEEK_END && off <= 0) { 311*66655411SSimon J. Gerraty if (ctx->vec_closing && ctx->vec_hashed < ctx->vec_size) { 312*66655411SSimon J. Gerraty DEBUG_PRINTF(3, ("%s: SEEK_END %ld\n", 313*66655411SSimon J. Gerraty __func__, 314*66655411SSimon J. Gerraty (long)(ctx->vec_size - ctx->vec_hashed))); 315*66655411SSimon J. Gerraty } 3165fff9558SSimon J. Gerraty whence = SEEK_SET; 3175fff9558SSimon J. Gerraty off += ctx->vec_size; 318afc571b1SSimon J. Gerraty } else if (whence == SEEK_CUR) { 3195fff9558SSimon J. Gerraty whence = SEEK_SET; 3205fff9558SSimon J. Gerraty off += ctx->vec_off; 3215fff9558SSimon J. Gerraty } 322afc571b1SSimon J. Gerraty if (whence != SEEK_SET || 323*66655411SSimon J. Gerraty off > ctx->vec_size) { 324*66655411SSimon J. Gerraty printf("ERROR: %s: unsupported operation: whence=%d off=%ld -> %ld\n", 325*66655411SSimon J. Gerraty __func__, whence, (long)ctx->vec_off, (long)off); 3265fff9558SSimon J. Gerraty return (-1); 3275fff9558SSimon J. Gerraty } 328afc571b1SSimon J. Gerraty if (off < ctx->vec_hashed) { 329*66655411SSimon J. Gerraty #ifdef _STANDALONE 330*66655411SSimon J. Gerraty struct open_file *f = fd2open_file(ctx->vec_fd); 331*66655411SSimon J. Gerraty 332*66655411SSimon J. Gerraty if (f != NULL && 333*66655411SSimon J. Gerraty strncmp(f->f_ops->fs_name, "tftp", 4) == 0) { 334*66655411SSimon J. Gerraty /* we cannot rewind if we've hashed much of the file */ 335*66655411SSimon J. Gerraty if (ctx->vec_hashed > ctx->vec_size / 5) 336*66655411SSimon J. Gerraty return (-1); /* refuse! */ 337*66655411SSimon J. Gerraty } 338*66655411SSimon J. Gerraty #endif 339afc571b1SSimon J. Gerraty /* seeking backwards! just do it */ 340afc571b1SSimon J. Gerraty ctx->vec_off = lseek(ctx->vec_fd, off, whence); 341afc571b1SSimon J. Gerraty return (ctx->vec_off); 342afc571b1SSimon J. Gerraty } 3435fff9558SSimon J. Gerraty n = 0; 3445fff9558SSimon J. Gerraty do { 3455fff9558SSimon J. Gerraty delta = off - ctx->vec_off; 3465fff9558SSimon J. Gerraty if (delta > 0) { 3475fff9558SSimon J. Gerraty delta = MIN(PAGE_SIZE, delta); 3485fff9558SSimon J. Gerraty n = vectx_read(ctx, buf, delta); 3495fff9558SSimon J. Gerraty if (n < 0) 3505fff9558SSimon J. Gerraty return (n); 3515fff9558SSimon J. Gerraty } 3525fff9558SSimon J. Gerraty } while (ctx->vec_off < off && n > 0); 3535fff9558SSimon J. Gerraty return (ctx->vec_off); 3545fff9558SSimon J. Gerraty } 3555fff9558SSimon J. Gerraty 3565fff9558SSimon J. Gerraty /** 3575fff9558SSimon J. Gerraty * @brief 3585fff9558SSimon J. Gerraty * check that hashes match and cleanup 3595fff9558SSimon J. Gerraty * 3605fff9558SSimon J. Gerraty * We have finished reading file, compare the hash with what 3615fff9558SSimon J. Gerraty * we wanted. 3625fff9558SSimon J. Gerraty * 36353f151f9SSimon J. Gerraty * Be sure to call this before closing the file, since we may 36453f151f9SSimon J. Gerraty * need to seek to the end to ensure hashing is complete. 36553f151f9SSimon J. Gerraty * 3665fff9558SSimon J. Gerraty * @param[in] pctx 3675fff9558SSimon J. Gerraty * pointer to ctx 3685fff9558SSimon J. Gerraty * 3695fff9558SSimon J. Gerraty * @return 0 or an error. 3705fff9558SSimon J. Gerraty */ 3715fff9558SSimon J. Gerraty int 372afc571b1SSimon J. Gerraty vectx_close(struct vectx *ctx, int severity, const char *caller) 3735fff9558SSimon J. Gerraty { 3745fff9558SSimon J. Gerraty int rc; 3755fff9558SSimon J. Gerraty 376*66655411SSimon J. Gerraty ctx->vec_closing = 1; 3775fff9558SSimon J. Gerraty if (ctx->vec_hashsz == 0) { 3785fff9558SSimon J. Gerraty rc = ctx->vec_status; 3795fff9558SSimon J. Gerraty } else { 380afc571b1SSimon J. Gerraty #ifdef VE_PCR_SUPPORT 381afc571b1SSimon J. Gerraty /* 382afc571b1SSimon J. Gerraty * Only update pcr with things that must verify 383afc571b1SSimon J. Gerraty * these tend to be processed in a more deterministic 384afc571b1SSimon J. Gerraty * order, which makes our pseudo pcr more useful. 385afc571b1SSimon J. Gerraty */ 386afc571b1SSimon J. Gerraty ve_pcr_updating_set((severity == VE_MUST)); 387afc571b1SSimon J. Gerraty #endif 38853f151f9SSimon J. Gerraty /* make sure we have hashed it all */ 38953f151f9SSimon J. Gerraty vectx_lseek(ctx, 0, SEEK_END); 3905fff9558SSimon J. Gerraty rc = ve_check_hash(&ctx->vec_ctx, ctx->vec_md, 3915fff9558SSimon J. Gerraty ctx->vec_path, ctx->vec_want, ctx->vec_hashsz); 3925fff9558SSimon J. Gerraty } 393afc571b1SSimon J. Gerraty DEBUG_PRINTF(2, 394afc571b1SSimon J. Gerraty ("vectx_close: caller=%s,name='%s',rc=%d,severity=%d\n", 395afc571b1SSimon J. Gerraty caller,ctx->vec_path, rc, severity)); 396*66655411SSimon J. Gerraty verify_report(ctx->vec_path, severity, rc, NULL); 39753f151f9SSimon J. Gerraty if (rc == VE_FINGERPRINT_WRONG) { 398afc571b1SSimon J. Gerraty #if !defined(UNIT_TEST) && !defined(DEBUG_VECTX) 399afc571b1SSimon J. Gerraty /* we are generally called with VE_MUST */ 40053f151f9SSimon J. Gerraty if (severity > VE_WANT) 401afc571b1SSimon J. Gerraty panic("cannot continue"); 402afc571b1SSimon J. Gerraty #endif 40353f151f9SSimon J. Gerraty } 4045fff9558SSimon J. Gerraty free(ctx); 4055fff9558SSimon J. Gerraty return ((rc < 0) ? rc : 0); 4065fff9558SSimon J. Gerraty } 407