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