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#include "../libsecureboot-priv.h"
27
28#include <unistd.h>
29#include <err.h>
30#include <verify_file.h>
31
32/* keep clang quiet */
33extern char *Destdir;
34extern size_t DestdirLen;
35extern char *Skip;
36extern time_t ve_utc;
37
38size_t DestdirLen;
39char *Destdir;
40char *Skip;
41
42int
43main(int argc, char *argv[])
44{
45	int n;
46	int fd;
47	int c;
48	int Vflag;
49	int vflag;
50	char *cp;
51	char *prefix;
52
53	Destdir = NULL;
54	DestdirLen = 0;
55	prefix = NULL;
56	Skip = NULL;
57
58	n = ve_trust_init();
59	Vflag = 0;
60	vflag = 0;
61
62	while ((c = getopt(argc, argv, "D:dp:s:T:u:Vv")) != -1) {
63		switch (c) {
64		case 'D':
65			Destdir = optarg;
66			DestdirLen = strlen(optarg);
67			break;
68		case 'd':
69			DebugVe++;
70			break;
71		case 'p':
72			prefix = optarg;
73			break;
74		case 's':
75			Skip = optarg;
76			break;
77		case 'T':
78			n = ve_trust_add(optarg);
79			printf("Local trust %s: %d\n", optarg, n);
80			break;
81		case 'V':
82			Vflag = 1;
83			break;
84		case 'v':
85			vflag = 1;
86			break;
87		case 'u':
88			ve_utc = (time_t)atoi(optarg);
89			break;
90		default:
91			errx(1, "unknown option: -%c", c);
92			break;
93		}
94	}
95
96	if (!vflag) {
97		printf("Trust %d\n", n);
98#ifdef VE_PCR_SUPPORT
99		ve_pcr_updating_set(1);
100#endif
101		ve_self_tests();
102	}
103	for ( ; optind < argc; optind++) {
104		if (Vflag) {
105			/*
106			 * Simulate what loader does.
107			 * verify_file should "just work"
108			 */
109			fd = open(argv[optind], O_RDONLY);
110			if (fd > 0) {
111				/*
112				 * See if verify_file is happy
113				 */
114				int x;
115
116				x = verify_file(fd, argv[optind], 0, VE_GUESS, __func__);
117				printf("verify_file(%s) = %d\n", argv[optind], x);
118				close(fd);
119			}
120			continue;
121		}
122#ifdef VE_OPENPGP_SUPPORT
123		if (strstr(argv[optind], "asc")) {
124			cp = (char *)verify_asc(argv[optind], 1);
125			if (cp) {
126				printf("Verified: %s: %.28s...\n",
127				    argv[optind], cp);
128				if (!vflag)
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
136#endif
137		if (strstr(argv[optind], "sig")) {
138			cp = (char *)verify_sig(argv[optind], 1);
139			if (cp) {
140				printf("Verified: %s: %.28s...\n",
141				    argv[optind], cp);
142				if (!vflag)
143					fingerprint_info_add(argv[optind],
144					    prefix, Skip, cp, NULL);
145			} else {
146				fprintf(stderr, "%s: %s\n",
147				    argv[optind], ve_error_get());
148			}
149		} else if (strstr(argv[optind], "manifest")) {
150			cp = (char *)read_file(argv[optind], NULL);
151			if (cp) {
152				fingerprint_info_add(argv[optind],
153				    prefix, Skip, cp, NULL);
154			}
155		} else {
156			fd = verify_open(argv[optind], O_RDONLY);
157			printf("verify_open(%s) = %d %s\n", argv[optind], fd,
158			    (fd < 0) ? ve_error_get() : "");
159			if (fd > 0) {
160				/*
161				 * Check that vectx_* can also verify the file.
162				 */
163				void *vp;
164				char buf[BUFSIZ];
165				struct stat st;
166				int error;
167				off_t off;
168				size_t nb;
169
170				fstat(fd, &st);
171				lseek(fd, 0, SEEK_SET);
172				off = st.st_size % 512;
173				vp = vectx_open(fd, argv[optind], off,
174				    &st, &error, __func__);
175				if (!vp) {
176					printf("vectx_open(%s) failed: %d %s\n",
177					    argv[optind], error,
178					    ve_error_get());
179				} else {
180					off = vectx_lseek(vp,
181					    (st.st_size % 1024), SEEK_SET);
182					/* we can seek backwards! */
183					off = vectx_lseek(vp, off/2, SEEK_SET);
184					if (off < st.st_size) {
185						nb = vectx_read(vp, buf,
186						    sizeof(buf));
187						if (nb > 0)
188							off += nb;
189					}
190					off = vectx_lseek(vp, 0, SEEK_END);
191					/* repeating that should be harmless */
192					off = vectx_lseek(vp, 0, SEEK_END);
193					error = vectx_close(vp, VE_MUST, __func__);
194					if (error) {
195						printf("vectx_close(%s) == %d %s\n",
196						    argv[optind], error,
197						    ve_error_get());
198					} else {
199						printf("vectx_close: Verified: %s\n",
200						    argv[optind]);
201					}
202				}
203				close(fd);
204			}
205		}
206	}
207#ifdef VE_PCR_SUPPORT
208	verify_pcr_export();
209	printf("pcr=%s\n", getenv("loader.ve.pcr"));
210#endif
211	return (0);
212}
213
214