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 #ifndef _STANDALONE
275fff9558SSimon J. Gerraty /* Avoid unwanted userlandish components */
285fff9558SSimon J. Gerraty #define _KERNEL
295fff9558SSimon J. Gerraty #include <sys/errno.h>
305fff9558SSimon J. Gerraty #undef _KERNEL
315fff9558SSimon J. Gerraty #endif
325fff9558SSimon J. Gerraty
3366655411SSimon J. Gerraty #ifdef VECTX_DEBUG
3466655411SSimon J. Gerraty static int vectx_debug = VECTX_DEBUG;
3566655411SSimon J. Gerraty # define DEBUG_PRINTF(n, x) if (vectx_debug >= n) printf x
3666655411SSimon J. Gerraty #endif
3766655411SSimon J. Gerraty
385fff9558SSimon J. Gerraty #include "libsecureboot-priv.h"
39afc571b1SSimon J. Gerraty #include <verify_file.h>
405fff9558SSimon J. Gerraty
415fff9558SSimon J. Gerraty /**
425fff9558SSimon J. Gerraty * @file vectx.c
435fff9558SSimon J. Gerraty * @brief api to verify file while reading
445fff9558SSimon J. Gerraty *
455fff9558SSimon J. Gerraty * This API allows the hash of a file to be computed as it is read.
465fff9558SSimon J. Gerraty * Key to this is seeking by reading.
475fff9558SSimon J. Gerraty *
485fff9558SSimon J. Gerraty * On close an indication of the verification result is returned.
495fff9558SSimon J. Gerraty */
505fff9558SSimon J. Gerraty
515fff9558SSimon J. Gerraty struct vectx {
525fff9558SSimon J. Gerraty br_hash_compat_context vec_ctx; /* hash ctx */
535fff9558SSimon J. Gerraty const br_hash_class *vec_md; /* hash method */
545fff9558SSimon J. Gerraty const char *vec_path; /* path we are verifying */
555fff9558SSimon J. Gerraty const char *vec_want; /* hash value we want */
565fff9558SSimon J. Gerraty off_t vec_off; /* current offset */
57afc571b1SSimon J. Gerraty off_t vec_hashed; /* where we have hashed to */
5866655411SSimon J. Gerraty off_t vec_size; /* size of path */
595fff9558SSimon J. Gerraty size_t vec_hashsz; /* size of hash */
605fff9558SSimon J. Gerraty int vec_fd; /* file descriptor */
615fff9558SSimon J. Gerraty int vec_status; /* verification status */
6266655411SSimon J. Gerraty int vec_closing; /* we are closing */
635fff9558SSimon J. Gerraty };
645fff9558SSimon J. Gerraty
65afc571b1SSimon J. Gerraty
665fff9558SSimon J. Gerraty /**
675fff9558SSimon J. Gerraty * @brief
685fff9558SSimon J. Gerraty * verify an open file as we read it
695fff9558SSimon J. Gerraty *
705fff9558SSimon J. Gerraty * If the file has no fingerprint to match, we will still return a
715fff9558SSimon J. Gerraty * verification context containing little more than the file
725fff9558SSimon J. Gerraty * descriptor, and an error code in @c error.
735fff9558SSimon J. Gerraty *
745fff9558SSimon J. Gerraty * @param[in] fd
755fff9558SSimon J. Gerraty * open descriptor
765fff9558SSimon J. Gerraty *
775fff9558SSimon J. Gerraty * @param[in] path
785fff9558SSimon J. Gerraty * pathname to open
795fff9558SSimon J. Gerraty *
805fff9558SSimon J. Gerraty * @param[in] off
815fff9558SSimon J. Gerraty * current offset
825fff9558SSimon J. Gerraty *
835fff9558SSimon J. Gerraty * @param[in] stp
845fff9558SSimon J. Gerraty * pointer to struct stat
855fff9558SSimon J. Gerraty *
865fff9558SSimon J. Gerraty * @param[out] error
875fff9558SSimon J. Gerraty * @li 0 all is good
885fff9558SSimon J. Gerraty * @li ENOMEM out of memory
895fff9558SSimon J. Gerraty * @li VE_FINGERPRINT_NONE no entry found
905fff9558SSimon J. Gerraty * @li VE_FINGERPRINT_UNKNOWN no fingerprint in entry
915fff9558SSimon J. Gerraty *
925fff9558SSimon J. Gerraty * @return ctx or NULL on error.
935fff9558SSimon J. Gerraty * NULL is only returned for non-files or out-of-memory.
945fff9558SSimon J. Gerraty */
955fff9558SSimon J. Gerraty struct vectx *
vectx_open(int fd,const char * path,off_t off,struct stat * stp,int * error,const char * caller)96afc571b1SSimon J. Gerraty vectx_open(int fd, const char *path, off_t off, struct stat *stp,
97afc571b1SSimon J. Gerraty int *error, const char *caller)
985fff9558SSimon J. Gerraty {
995fff9558SSimon J. Gerraty struct vectx *ctx;
1005fff9558SSimon J. Gerraty struct stat st;
1015fff9558SSimon J. Gerraty size_t hashsz;
1025fff9558SSimon J. Gerraty char *cp;
103afc571b1SSimon J. Gerraty int rc;
1045fff9558SSimon J. Gerraty
105afc571b1SSimon J. Gerraty if (!stp)
1065fff9558SSimon J. Gerraty stp = &st;
1075fff9558SSimon J. Gerraty
108afc571b1SSimon J. Gerraty rc = verify_prep(fd, path, off, stp, __func__);
109afc571b1SSimon J. Gerraty
110afc571b1SSimon J. Gerraty DEBUG_PRINTF(2,
11153f151f9SSimon J. Gerraty ("vectx_open: caller=%s,fd=%d,name='%s',prep_rc=%d\n",
11253f151f9SSimon J. Gerraty caller, fd, path, rc));
113afc571b1SSimon J. Gerraty
114afc571b1SSimon J. Gerraty switch (rc) {
115afc571b1SSimon J. Gerraty case VE_FINGERPRINT_NONE:
116afc571b1SSimon J. Gerraty case VE_FINGERPRINT_UNKNOWN:
117afc571b1SSimon J. Gerraty case VE_FINGERPRINT_WRONG:
118afc571b1SSimon J. Gerraty *error = rc;
1195fff9558SSimon J. Gerraty return (NULL);
1205fff9558SSimon J. Gerraty }
1215fff9558SSimon J. Gerraty ctx = malloc(sizeof(struct vectx));
1225fff9558SSimon J. Gerraty if (!ctx)
1235fff9558SSimon J. Gerraty goto enomem;
1245fff9558SSimon J. Gerraty ctx->vec_fd = fd;
1255fff9558SSimon J. Gerraty ctx->vec_path = path;
1265fff9558SSimon J. Gerraty ctx->vec_size = stp->st_size;
1275fff9558SSimon J. Gerraty ctx->vec_off = 0;
128afc571b1SSimon J. Gerraty ctx->vec_hashed = 0;
1295fff9558SSimon J. Gerraty ctx->vec_want = NULL;
1305fff9558SSimon J. Gerraty ctx->vec_status = 0;
131afc571b1SSimon J. Gerraty ctx->vec_hashsz = hashsz = 0;
13266655411SSimon J. Gerraty ctx->vec_closing = 0;
1335fff9558SSimon J. Gerraty
134afc571b1SSimon J. Gerraty if (rc == 0) {
135afc571b1SSimon J. Gerraty /* we are not verifying this */
136afc571b1SSimon J. Gerraty *error = 0;
137afc571b1SSimon J. Gerraty return (ctx);
138afc571b1SSimon J. Gerraty }
1395fff9558SSimon J. Gerraty cp = fingerprint_info_lookup(fd, path);
1405fff9558SSimon J. Gerraty if (!cp) {
1415fff9558SSimon J. Gerraty ctx->vec_status = VE_FINGERPRINT_NONE;
1425fff9558SSimon J. Gerraty ve_error_set("%s: no entry", path);
1435fff9558SSimon J. Gerraty } else {
14464ca9a7fSSimon J. Gerraty if (strncmp(cp, "no_hash", 7) == 0) {
14564ca9a7fSSimon J. Gerraty ctx->vec_status = VE_FINGERPRINT_IGNORE;
14664ca9a7fSSimon J. Gerraty hashsz = 0;
14764ca9a7fSSimon J. Gerraty } else if (strncmp(cp, "sha256=", 7) == 0) {
1485fff9558SSimon J. Gerraty ctx->vec_md = &br_sha256_vtable;
1495fff9558SSimon J. Gerraty hashsz = br_sha256_SIZE;
1505fff9558SSimon J. Gerraty cp += 7;
1515fff9558SSimon J. Gerraty #ifdef VE_SHA1_SUPPORT
1525fff9558SSimon J. Gerraty } else if (strncmp(cp, "sha1=", 5) == 0) {
1535fff9558SSimon J. Gerraty ctx->vec_md = &br_sha1_vtable;
1545fff9558SSimon J. Gerraty hashsz = br_sha1_SIZE;
1555fff9558SSimon J. Gerraty cp += 5;
1565fff9558SSimon J. Gerraty #endif
1575fff9558SSimon J. Gerraty #ifdef VE_SHA384_SUPPORT
1585fff9558SSimon J. Gerraty } else if (strncmp(cp, "sha384=", 7) == 0) {
1595fff9558SSimon J. Gerraty ctx->vec_md = &br_sha384_vtable;
1605fff9558SSimon J. Gerraty hashsz = br_sha384_SIZE;
1615fff9558SSimon J. Gerraty cp += 7;
1625fff9558SSimon J. Gerraty #endif
1635fff9558SSimon J. Gerraty #ifdef VE_SHA512_SUPPORT
1645fff9558SSimon J. Gerraty } else if (strncmp(cp, "sha512=", 7) == 0) {
1655fff9558SSimon J. Gerraty ctx->vec_md = &br_sha512_vtable;
1665fff9558SSimon J. Gerraty hashsz = br_sha512_SIZE;
1675fff9558SSimon J. Gerraty cp += 7;
1685fff9558SSimon J. Gerraty #endif
1695fff9558SSimon J. Gerraty } else {
1705fff9558SSimon J. Gerraty ctx->vec_status = VE_FINGERPRINT_UNKNOWN;
1715fff9558SSimon J. Gerraty ve_error_set("%s: no supported fingerprint", path);
1725fff9558SSimon J. Gerraty }
1735fff9558SSimon J. Gerraty }
1745fff9558SSimon J. Gerraty *error = ctx->vec_status;
1755fff9558SSimon J. Gerraty ctx->vec_hashsz = hashsz;
1765fff9558SSimon J. Gerraty ctx->vec_want = cp;
17764ca9a7fSSimon J. Gerraty if (hashsz > 0) {
1785fff9558SSimon J. Gerraty ctx->vec_md->init(&ctx->vec_ctx.vtable);
1795fff9558SSimon J. Gerraty
18064ca9a7fSSimon J. Gerraty if (off > 0) {
1815fff9558SSimon J. Gerraty lseek(fd, 0, SEEK_SET);
1825fff9558SSimon J. Gerraty vectx_lseek(ctx, off, SEEK_SET);
1835fff9558SSimon J. Gerraty }
18464ca9a7fSSimon J. Gerraty }
185afc571b1SSimon J. Gerraty DEBUG_PRINTF(2,
186afc571b1SSimon J. Gerraty ("vectx_open: caller=%s,name='%s',hashsz=%lu,status=%d\n",
187afc571b1SSimon J. Gerraty caller, path, (unsigned long)ctx->vec_hashsz,
188afc571b1SSimon J. Gerraty ctx->vec_status));
1895fff9558SSimon J. Gerraty return (ctx);
1905fff9558SSimon J. Gerraty
1915fff9558SSimon J. Gerraty enomem: /* unlikely */
1925fff9558SSimon J. Gerraty *error = ENOMEM;
1935fff9558SSimon J. Gerraty free(ctx);
1945fff9558SSimon J. Gerraty return (NULL);
1955fff9558SSimon J. Gerraty }
1965fff9558SSimon J. Gerraty
1975fff9558SSimon J. Gerraty /**
1985fff9558SSimon J. Gerraty * @brief
1995fff9558SSimon J. Gerraty * read bytes from file and update hash
2005fff9558SSimon J. Gerraty *
2015fff9558SSimon J. Gerraty * It is critical that all file I/O comes through here.
2025fff9558SSimon J. Gerraty * We keep track of current offset.
203afc571b1SSimon J. Gerraty * We also track what offset we have hashed to,
204afc571b1SSimon J. Gerraty * so we won't replay data if we seek backwards.
2055fff9558SSimon J. Gerraty *
2065fff9558SSimon J. Gerraty * @param[in] pctx
2075fff9558SSimon J. Gerraty * pointer to ctx
2085fff9558SSimon J. Gerraty *
2095fff9558SSimon J. Gerraty * @param[in] buf
2105fff9558SSimon J. Gerraty *
2115fff9558SSimon J. Gerraty * @param[in] nbytes
2125fff9558SSimon J. Gerraty *
2135fff9558SSimon J. Gerraty * @return bytes read or error.
2145fff9558SSimon J. Gerraty */
2155fff9558SSimon J. Gerraty ssize_t
vectx_read(struct vectx * ctx,void * buf,size_t nbytes)2165fff9558SSimon J. Gerraty vectx_read(struct vectx *ctx, void *buf, size_t nbytes)
2175fff9558SSimon J. Gerraty {
2185fff9558SSimon J. Gerraty unsigned char *bp = buf;
219723f9041SSimon J. Gerraty int d;
2205fff9558SSimon J. Gerraty int n;
221afc571b1SSimon J. Gerraty int delta;
222afc571b1SSimon J. Gerraty int x;
2235fff9558SSimon J. Gerraty size_t off;
2245fff9558SSimon J. Gerraty
2255fff9558SSimon J. Gerraty if (ctx->vec_hashsz == 0) /* nothing to do */
2265fff9558SSimon J. Gerraty return (read(ctx->vec_fd, buf, nbytes));
2275fff9558SSimon J. Gerraty
2285fff9558SSimon J. Gerraty off = 0;
2295fff9558SSimon J. Gerraty do {
230723f9041SSimon J. Gerraty /*
231723f9041SSimon J. Gerraty * Do this in reasonable chunks so
232723f9041SSimon J. Gerraty * we don't timeout if doing tftp
233723f9041SSimon J. Gerraty */
234723f9041SSimon J. Gerraty x = nbytes - off;
235723f9041SSimon J. Gerraty x = MIN(PAGE_SIZE, x);
236723f9041SSimon J. Gerraty d = n = read(ctx->vec_fd, &bp[off], x);
23766655411SSimon J. Gerraty if (ctx->vec_closing && n < x) {
23866655411SSimon J. Gerraty DEBUG_PRINTF(3,
23966655411SSimon J. Gerraty ("%s: read %d off=%ld hashed=%ld size=%ld\n",
24066655411SSimon J. Gerraty __func__, n, (long)ctx->vec_off,
24166655411SSimon J. Gerraty (long)ctx->vec_hashed, (long)ctx->vec_size));
24266655411SSimon J. Gerraty }
243723f9041SSimon J. Gerraty if (n < 0) {
2445fff9558SSimon J. Gerraty return (n);
245723f9041SSimon J. Gerraty }
246723f9041SSimon J. Gerraty if (d > 0) {
247afc571b1SSimon J. Gerraty /* we may have seeked backwards! */
248afc571b1SSimon J. Gerraty delta = ctx->vec_hashed - ctx->vec_off;
249afc571b1SSimon J. Gerraty if (delta > 0) {
250723f9041SSimon J. Gerraty x = MIN(delta, d);
251afc571b1SSimon J. Gerraty off += x;
252723f9041SSimon J. Gerraty d -= x;
253afc571b1SSimon J. Gerraty ctx->vec_off += x;
254afc571b1SSimon J. Gerraty }
255723f9041SSimon J. Gerraty if (d > 0) {
25666655411SSimon J. Gerraty if (ctx->vec_closing && d < PAGE_SIZE) {
25766655411SSimon J. Gerraty DEBUG_PRINTF(3,
25866655411SSimon J. Gerraty ("%s: update %ld + %d\n",
25966655411SSimon J. Gerraty __func__,
26066655411SSimon J. Gerraty (long)ctx->vec_hashed, d));
26166655411SSimon J. Gerraty }
262723f9041SSimon J. Gerraty ctx->vec_md->update(&ctx->vec_ctx.vtable, &bp[off], d);
263723f9041SSimon J. Gerraty off += d;
264723f9041SSimon J. Gerraty ctx->vec_off += d;
265723f9041SSimon J. Gerraty ctx->vec_hashed += d;
266afc571b1SSimon J. Gerraty }
2675fff9558SSimon J. Gerraty }
2685fff9558SSimon J. Gerraty } while (n > 0 && off < nbytes);
2695fff9558SSimon J. Gerraty return (off);
2705fff9558SSimon J. Gerraty }
2715fff9558SSimon J. Gerraty
2725fff9558SSimon J. Gerraty /**
2735fff9558SSimon J. Gerraty * @brief
2745fff9558SSimon J. Gerraty * vectx equivalent of lseek
2755fff9558SSimon J. Gerraty *
276afc571b1SSimon J. Gerraty * When seeking forwards we actually call vectx_read
2775fff9558SSimon J. Gerraty * to reach the desired offset.
2785fff9558SSimon J. Gerraty *
279afc571b1SSimon J. Gerraty * We support seeking backwards.
2805fff9558SSimon J. Gerraty *
2815fff9558SSimon J. Gerraty * @param[in] pctx
2825fff9558SSimon J. Gerraty * pointer to ctx
2835fff9558SSimon J. Gerraty *
2845fff9558SSimon J. Gerraty * @param[in] off
2855fff9558SSimon J. Gerraty * desired offset
2865fff9558SSimon J. Gerraty *
2875fff9558SSimon J. Gerraty * @param[in] whence
288afc571b1SSimon J. Gerraty * We try to convert whence to ``SEEK_SET``.
289afc571b1SSimon J. Gerraty * We do not support ``SEEK_DATA`` or ``SEEK_HOLE``.
2905fff9558SSimon J. Gerraty *
2915fff9558SSimon J. Gerraty * @return offset or error.
2925fff9558SSimon J. Gerraty */
2935fff9558SSimon J. Gerraty off_t
vectx_lseek(struct vectx * ctx,off_t off,int whence)2945fff9558SSimon J. Gerraty vectx_lseek(struct vectx *ctx, off_t off, int whence)
2955fff9558SSimon J. Gerraty {
2965fff9558SSimon J. Gerraty unsigned char buf[PAGE_SIZE];
2975fff9558SSimon J. Gerraty size_t delta;
2985fff9558SSimon J. Gerraty ssize_t n;
2995fff9558SSimon J. Gerraty
3005fff9558SSimon J. Gerraty if (ctx->vec_hashsz == 0) /* nothing to do */
3015fff9558SSimon J. Gerraty return (lseek(ctx->vec_fd, off, whence));
3025fff9558SSimon J. Gerraty
3035fff9558SSimon J. Gerraty /*
304afc571b1SSimon J. Gerraty * Convert whence to SEEK_SET
3055fff9558SSimon J. Gerraty */
30666655411SSimon J. Gerraty DEBUG_PRINTF(3,
30766655411SSimon J. Gerraty ("%s(%s, %ld, %d)\n", __func__, ctx->vec_path, (long)off, whence));
3085fff9558SSimon J. Gerraty if (whence == SEEK_END && off <= 0) {
309*f616d61aSSimon J. Gerraty if (ctx->vec_size < 0) {
310*f616d61aSSimon J. Gerraty if (ctx->vec_closing) {
311*f616d61aSSimon J. Gerraty /* size unknown - read until EOF */
312*f616d61aSSimon J. Gerraty do {
313*f616d61aSSimon J. Gerraty n = vectx_read(ctx, buf, PAGE_SIZE);
314*f616d61aSSimon J. Gerraty if (n < 0)
315*f616d61aSSimon J. Gerraty return (n);
316*f616d61aSSimon J. Gerraty } while (n > 0);
317*f616d61aSSimon J. Gerraty return (ctx->vec_off);
318*f616d61aSSimon J. Gerraty }
319*f616d61aSSimon J. Gerraty } else {
32066655411SSimon J. Gerraty if (ctx->vec_closing && ctx->vec_hashed < ctx->vec_size) {
32166655411SSimon J. Gerraty DEBUG_PRINTF(3, ("%s: SEEK_END %ld\n",
32266655411SSimon J. Gerraty __func__,
32366655411SSimon J. Gerraty (long)(ctx->vec_size - ctx->vec_hashed)));
32466655411SSimon J. Gerraty }
3255fff9558SSimon J. Gerraty whence = SEEK_SET;
3265fff9558SSimon J. Gerraty off += ctx->vec_size;
327*f616d61aSSimon J. Gerraty }
328afc571b1SSimon J. Gerraty } else if (whence == SEEK_CUR) {
3295fff9558SSimon J. Gerraty whence = SEEK_SET;
3305fff9558SSimon J. Gerraty off += ctx->vec_off;
3315fff9558SSimon J. Gerraty }
332afc571b1SSimon J. Gerraty if (whence != SEEK_SET ||
333*f616d61aSSimon J. Gerraty (off > ctx->vec_size && ctx->vec_size > 0)) {
33466655411SSimon J. Gerraty printf("ERROR: %s: unsupported operation: whence=%d off=%ld -> %ld\n",
33566655411SSimon J. Gerraty __func__, whence, (long)ctx->vec_off, (long)off);
3365fff9558SSimon J. Gerraty return (-1);
3375fff9558SSimon J. Gerraty }
338afc571b1SSimon J. Gerraty if (off < ctx->vec_hashed) {
33966655411SSimon J. Gerraty #ifdef _STANDALONE
34066655411SSimon J. Gerraty struct open_file *f = fd2open_file(ctx->vec_fd);
34166655411SSimon J. Gerraty
34266655411SSimon J. Gerraty if (f != NULL &&
34366655411SSimon J. Gerraty strncmp(f->f_ops->fs_name, "tftp", 4) == 0) {
34466655411SSimon J. Gerraty /* we cannot rewind if we've hashed much of the file */
34566655411SSimon J. Gerraty if (ctx->vec_hashed > ctx->vec_size / 5)
34666655411SSimon J. Gerraty return (-1); /* refuse! */
34766655411SSimon J. Gerraty }
34866655411SSimon J. Gerraty #endif
349afc571b1SSimon J. Gerraty /* seeking backwards! just do it */
350afc571b1SSimon J. Gerraty ctx->vec_off = lseek(ctx->vec_fd, off, whence);
351afc571b1SSimon J. Gerraty return (ctx->vec_off);
352afc571b1SSimon J. Gerraty }
3535fff9558SSimon J. Gerraty n = 0;
3545fff9558SSimon J. Gerraty do {
3555fff9558SSimon J. Gerraty delta = off - ctx->vec_off;
3565fff9558SSimon J. Gerraty if (delta > 0) {
3575fff9558SSimon J. Gerraty delta = MIN(PAGE_SIZE, delta);
3585fff9558SSimon J. Gerraty n = vectx_read(ctx, buf, delta);
3595fff9558SSimon J. Gerraty if (n < 0)
3605fff9558SSimon J. Gerraty return (n);
3615fff9558SSimon J. Gerraty }
3625fff9558SSimon J. Gerraty } while (ctx->vec_off < off && n > 0);
3635fff9558SSimon J. Gerraty return (ctx->vec_off);
3645fff9558SSimon J. Gerraty }
3655fff9558SSimon J. Gerraty
3665fff9558SSimon J. Gerraty /**
3675fff9558SSimon J. Gerraty * @brief
3685fff9558SSimon J. Gerraty * check that hashes match and cleanup
3695fff9558SSimon J. Gerraty *
3705fff9558SSimon J. Gerraty * We have finished reading file, compare the hash with what
3715fff9558SSimon J. Gerraty * we wanted.
3725fff9558SSimon J. Gerraty *
37353f151f9SSimon J. Gerraty * Be sure to call this before closing the file, since we may
37453f151f9SSimon J. Gerraty * need to seek to the end to ensure hashing is complete.
37553f151f9SSimon J. Gerraty *
3765fff9558SSimon J. Gerraty * @param[in] pctx
3775fff9558SSimon J. Gerraty * pointer to ctx
3785fff9558SSimon J. Gerraty *
3795fff9558SSimon J. Gerraty * @return 0 or an error.
3805fff9558SSimon J. Gerraty */
3815fff9558SSimon J. Gerraty int
vectx_close(struct vectx * ctx,int severity,const char * caller)382afc571b1SSimon J. Gerraty vectx_close(struct vectx *ctx, int severity, const char *caller)
3835fff9558SSimon J. Gerraty {
3845fff9558SSimon J. Gerraty int rc;
3855fff9558SSimon J. Gerraty
38666655411SSimon J. Gerraty ctx->vec_closing = 1;
3875fff9558SSimon J. Gerraty if (ctx->vec_hashsz == 0) {
3885fff9558SSimon J. Gerraty rc = ctx->vec_status;
3895fff9558SSimon J. Gerraty } else {
390afc571b1SSimon J. Gerraty #ifdef VE_PCR_SUPPORT
391afc571b1SSimon J. Gerraty /*
392afc571b1SSimon J. Gerraty * Only update pcr with things that must verify
393afc571b1SSimon J. Gerraty * these tend to be processed in a more deterministic
394afc571b1SSimon J. Gerraty * order, which makes our pseudo pcr more useful.
395afc571b1SSimon J. Gerraty */
396afc571b1SSimon J. Gerraty ve_pcr_updating_set((severity == VE_MUST));
397afc571b1SSimon J. Gerraty #endif
39853f151f9SSimon J. Gerraty /* make sure we have hashed it all */
39953f151f9SSimon J. Gerraty vectx_lseek(ctx, 0, SEEK_END);
4005fff9558SSimon J. Gerraty rc = ve_check_hash(&ctx->vec_ctx, ctx->vec_md,
4015fff9558SSimon J. Gerraty ctx->vec_path, ctx->vec_want, ctx->vec_hashsz);
4025fff9558SSimon J. Gerraty }
403afc571b1SSimon J. Gerraty DEBUG_PRINTF(2,
404afc571b1SSimon J. Gerraty ("vectx_close: caller=%s,name='%s',rc=%d,severity=%d\n",
405afc571b1SSimon J. Gerraty caller,ctx->vec_path, rc, severity));
40666655411SSimon J. Gerraty verify_report(ctx->vec_path, severity, rc, NULL);
40753f151f9SSimon J. Gerraty if (rc == VE_FINGERPRINT_WRONG) {
408afc571b1SSimon J. Gerraty #if !defined(UNIT_TEST) && !defined(DEBUG_VECTX)
409afc571b1SSimon J. Gerraty /* we are generally called with VE_MUST */
41053f151f9SSimon J. Gerraty if (severity > VE_WANT)
411afc571b1SSimon J. Gerraty panic("cannot continue");
412afc571b1SSimon J. Gerraty #endif
41353f151f9SSimon J. Gerraty }
4145fff9558SSimon J. Gerraty free(ctx);
4155fff9558SSimon J. Gerraty return ((rc < 0) ? rc : 0);
4165fff9558SSimon J. Gerraty }
417