xref: /freebsd/lib/libsecureboot/tests/tvo.c (revision 2e3507c25e42292b45a5482e116d278f5515d04d)
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 */
33 extern char *Destdir;
34 extern size_t DestdirLen;
35 extern char *Skip;
36 extern time_t ve_utc;
37 
38 size_t DestdirLen;
39 char *Destdir;
40 char *Skip;
41 
42 int
43 main(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