1/*
2 * Copyright (c) 2017-2018, Juniper Networks, Inc.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
14 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
15 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
16 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
17 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
18 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
19 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25#include <sys/cdefs.h>
26__FBSDID("$FreeBSD$");
27
28#include "../libsecureboot-priv.h"
29
30#include <unistd.h>
31#include <err.h>
32#include <verify_file.h>
33
34size_t DestdirLen;
35char *Destdir;
36char *Skip;
37
38int
39main(int argc, char *argv[])
40{
41	int n;
42	int fd;
43	int c;
44	int Vflag;
45	char *cp;
46	char *prefix;
47	char *destdir;
48
49	Destdir = NULL;
50	DestdirLen = 0;
51	prefix = NULL;
52	Skip = NULL;
53
54	n = ve_trust_init();
55	printf("Trust %d\n", n);
56	Vflag = 0;
57
58	while ((c = getopt(argc, argv, "D:dp:s:T:V")) != -1) {
59		switch (c) {
60		case 'D':
61			Destdir = optarg;
62			DestdirLen = strlen(optarg);
63			break;
64		case 'd':
65			DebugVe++;
66			break;
67		case 'p':
68			prefix = optarg;
69			break;
70		case 's':
71			Skip = optarg;
72			break;
73		case 'T':
74			n = ve_trust_add(optarg);
75			printf("Local trust %s: %d\n", optarg, n);
76			break;
77		case 'V':
78			Vflag = 1;
79			break;
80		default:
81			errx(1, "unknown option: -%c", c);
82			break;
83		}
84	}
85
86#ifdef VE_PCR_SUPPORT
87	ve_pcr_updating_set(1);
88#endif
89	ve_self_tests();
90
91	for ( ; optind < argc; optind++) {
92		if (Vflag) {
93			/*
94			 * Simulate what loader does.
95			 * verify_file should "just work"
96			 */
97			fd = open(argv[optind], O_RDONLY);
98			if (fd > 0) {
99				/*
100				 * See if verify_file is happy
101				 */
102				int x;
103
104				x = verify_file(fd, argv[optind], 0, VE_GUESS, __func__);
105				printf("verify_file(%s) = %d\n", argv[optind], x);
106				close(fd);
107			}
108			continue;
109		}
110#ifdef VE_OPENPGP_SUPPORT
111		if (strstr(argv[optind], "asc")) {
112			cp = (char *)verify_asc(argv[optind], 1);
113			if (cp) {
114				printf("Verified: %s: %.28s...\n",
115				    argv[optind], cp);
116				fingerprint_info_add(argv[optind],
117				    prefix, Skip, cp, NULL);
118			} else {
119				fprintf(stderr, "%s: %s\n",
120				    argv[optind], ve_error_get());
121			}
122		} else
123#endif
124		if (strstr(argv[optind], "sig")) {
125			cp = (char *)verify_sig(argv[optind], 1);
126			if (cp) {
127				printf("Verified: %s: %.28s...\n",
128				    argv[optind], cp);
129				fingerprint_info_add(argv[optind],
130				    prefix, Skip, cp, NULL);
131			} else {
132				fprintf(stderr, "%s: %s\n",
133				    argv[optind], ve_error_get());
134			}
135		} else if (strstr(argv[optind], "manifest")) {
136			cp = (char *)read_file(argv[optind], NULL);
137			if (cp) {
138				fingerprint_info_add(argv[optind],
139				    prefix, Skip, cp, NULL);
140			}
141		} else {
142			fd = verify_open(argv[optind], O_RDONLY);
143			printf("verify_open(%s) = %d %s\n", argv[optind], fd,
144			    (fd < 0) ? ve_error_get() : "");
145			if (fd > 0) {
146				/*
147				 * Check that vectx_* can also verify the file.
148				 */
149				void *vp;
150				char buf[BUFSIZ];
151				struct stat st;
152				int error;
153				size_t off, n;
154
155				fstat(fd, &st);
156				lseek(fd, 0, SEEK_SET);
157				off = st.st_size % 512;
158				vp = vectx_open(fd, argv[optind], off,
159				    &st, &error, __func__);
160				if (!vp) {
161					printf("vectx_open(%s) failed: %d %s\n",
162					    argv[optind], error,
163					    ve_error_get());
164				} else {
165					off = vectx_lseek(vp,
166					    (st.st_size % 1024), SEEK_SET);
167					/* we can seek backwards! */
168					off = vectx_lseek(vp, off/2, SEEK_SET);
169					if (off < st.st_size) {
170						n = vectx_read(vp, buf,
171						    sizeof(buf));
172						if (n > 0)
173							off += n;
174					}
175					off = vectx_lseek(vp, 0, SEEK_END);
176					/* repeating that should be harmless */
177					off = vectx_lseek(vp, 0, SEEK_END);
178					error = vectx_close(vp, VE_MUST, __func__);
179					if (error) {
180						printf("vectx_close(%s) == %d %s\n",
181						    argv[optind], error,
182						    ve_error_get());
183					} else {
184						printf("vectx_close: Verified: %s\n",
185						    argv[optind]);
186					}
187				}
188				close(fd);
189			}
190		}
191	}
192#ifdef VE_PCR_SUPPORT
193	verify_pcr_export();
194	printf("pcr=%s\n", getenv("loader.ve.pcr"));
195#endif
196	return (0);
197}
198
199