xref: /freebsd/lib/libsecureboot/vectx.c (revision 666554111a7e6b4c1a9a6ff2e73f12cd582573bb)
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