1eb12b8eaSSimon J. Gerraty %{
2eb12b8eaSSimon J. Gerraty /*-
3eb12b8eaSSimon J. Gerraty * Copyright (c) 2004-2018, Juniper Networks, Inc.
4eb12b8eaSSimon J. Gerraty *
5eb12b8eaSSimon J. Gerraty * Redistribution and use in source and binary forms, with or without
6eb12b8eaSSimon J. Gerraty * modification, are permitted provided that the following conditions
7eb12b8eaSSimon J. Gerraty * are met:
8eb12b8eaSSimon J. Gerraty * 1. Redistributions of source code must retain the above copyright
9eb12b8eaSSimon J. Gerraty * notice, this list of conditions and the following disclaimer.
10eb12b8eaSSimon J. Gerraty * 2. Redistributions in binary form must reproduce the above copyright
11eb12b8eaSSimon J. Gerraty * notice, this list of conditions and the following disclaimer in the
12eb12b8eaSSimon J. Gerraty * documentation and/or other materials provided with the distribution.
13eb12b8eaSSimon J. Gerraty *
14eb12b8eaSSimon J. Gerraty * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15eb12b8eaSSimon J. Gerraty * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16eb12b8eaSSimon J. Gerraty * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17eb12b8eaSSimon J. Gerraty * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
18eb12b8eaSSimon J. Gerraty * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19eb12b8eaSSimon J. Gerraty * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
20eb12b8eaSSimon J. Gerraty * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21eb12b8eaSSimon J. Gerraty * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22eb12b8eaSSimon J. Gerraty * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23eb12b8eaSSimon J. Gerraty * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24eb12b8eaSSimon J. Gerraty * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25eb12b8eaSSimon J. Gerraty */
26eb12b8eaSSimon J. Gerraty
27eb12b8eaSSimon J. Gerraty #include <sys/stat.h>
28eb12b8eaSSimon J. Gerraty #include <stdio.h>
29eb12b8eaSSimon J. Gerraty #include <ctype.h>
30eb12b8eaSSimon J. Gerraty #include <err.h>
31eb12b8eaSSimon J. Gerraty #include <sysexits.h>
32eb12b8eaSSimon J. Gerraty #include <libsecureboot.h>
33eb12b8eaSSimon J. Gerraty
34eb12b8eaSSimon J. Gerraty #include "veriexec.h"
35eb12b8eaSSimon J. Gerraty
36eb12b8eaSSimon J. Gerraty int yylex(void);
37eb12b8eaSSimon J. Gerraty void yyerror(const char *);
38eb12b8eaSSimon J. Gerraty
39eb12b8eaSSimon J. Gerraty /* function prototypes */
40eb12b8eaSSimon J. Gerraty static int convert(char *fp, unsigned int count, unsigned char *out);
41eb12b8eaSSimon J. Gerraty static void do_ioctl(void);
42eb12b8eaSSimon J. Gerraty static int get_fingerprint_type(const char *fp_type);
43eb12b8eaSSimon J. Gerraty
44eb12b8eaSSimon J. Gerraty /* ioctl parameter struct */
45eb12b8eaSSimon J. Gerraty #ifdef MAXLABELLEN
46eb12b8eaSSimon J. Gerraty static struct verified_exec_label_params lparams;
47eb12b8eaSSimon J. Gerraty static struct verified_exec_params *params = &lparams.params;
48eb12b8eaSSimon J. Gerraty #else
49eb12b8eaSSimon J. Gerraty static struct verified_exec_params oparams;
50eb12b8eaSSimon J. Gerraty static struct verified_exec_params *params = &oparams;
51eb12b8eaSSimon J. Gerraty #endif
52eb12b8eaSSimon J. Gerraty
53eb12b8eaSSimon J. Gerraty #ifndef SHA256_DIGEST_LENGTH
54eb12b8eaSSimon J. Gerraty # define SHA_DIGEST_LENGTH br_sha1_SIZE
55eb12b8eaSSimon J. Gerraty # define SHA256_DIGEST_LENGTH br_sha256_SIZE
56eb12b8eaSSimon J. Gerraty # define SHA384_DIGEST_LENGTH br_sha384_SIZE
57*2e6a4338SStephen J. Kiernan # define SHA512_DIGEST_LENGTH br_sha512_SIZE
58eb12b8eaSSimon J. Gerraty #endif
59eb12b8eaSSimon J. Gerraty
60eb12b8eaSSimon J. Gerraty static int fmode;
61eb12b8eaSSimon J. Gerraty
62eb12b8eaSSimon J. Gerraty extern int lineno;
63eb12b8eaSSimon J. Gerraty extern int dev_fd;
64eb12b8eaSSimon J. Gerraty
65eb12b8eaSSimon J. Gerraty struct fingerprint_type {
66eb12b8eaSSimon J. Gerraty const char *fp_type;
67eb12b8eaSSimon J. Gerraty int fp_size;
68eb12b8eaSSimon J. Gerraty };
69eb12b8eaSSimon J. Gerraty
70eb12b8eaSSimon J. Gerraty /* static globals */
71eb12b8eaSSimon J. Gerraty static const struct fingerprint_type fingerprint_table[] = {
72eb12b8eaSSimon J. Gerraty { "sha1", SHA_DIGEST_LENGTH },
73eb12b8eaSSimon J. Gerraty { "sha256", SHA256_DIGEST_LENGTH },
74eb12b8eaSSimon J. Gerraty { "sha384", SHA384_DIGEST_LENGTH },
75*2e6a4338SStephen J. Kiernan { "sha512", SHA512_DIGEST_LENGTH },
76eb12b8eaSSimon J. Gerraty { NULL, 0 }
77eb12b8eaSSimon J. Gerraty };
78eb12b8eaSSimon J. Gerraty
79eb12b8eaSSimon J. Gerraty /*
80eb12b8eaSSimon J. Gerraty * Indicate to lexer our version.
81eb12b8eaSSimon J. Gerraty * A token #>NUMBER will be consumed (and discared)
82eb12b8eaSSimon J. Gerraty * by lexer if parser_version > NUMBER
83eb12b8eaSSimon J. Gerraty * Otherwise the rest of the line will be discared
84eb12b8eaSSimon J. Gerraty * as for a comment.
85eb12b8eaSSimon J. Gerraty */
86eb12b8eaSSimon J. Gerraty int parser_version = 1;
87eb12b8eaSSimon J. Gerraty
88eb12b8eaSSimon J. Gerraty %}
89eb12b8eaSSimon J. Gerraty
90eb12b8eaSSimon J. Gerraty %union {
91eb12b8eaSSimon J. Gerraty char *string;
92eb12b8eaSSimon J. Gerraty int intval;
93eb12b8eaSSimon J. Gerraty }
94eb12b8eaSSimon J. Gerraty
95eb12b8eaSSimon J. Gerraty %token EOL
96eb12b8eaSSimon J. Gerraty %token <string> EQ
97eb12b8eaSSimon J. Gerraty %token <string> PATH
98eb12b8eaSSimon J. Gerraty %token <string> STRING
99eb12b8eaSSimon J. Gerraty
100eb12b8eaSSimon J. Gerraty %%
101eb12b8eaSSimon J. Gerraty
102eb12b8eaSSimon J. Gerraty statement: /* empty */
103eb12b8eaSSimon J. Gerraty | statement path attributes eol
104eb12b8eaSSimon J. Gerraty | statement error eol {
105eb12b8eaSSimon J. Gerraty yyclearin; /* discard lookahead */
106eb12b8eaSSimon J. Gerraty yyerrok; /* no more error */
107eb12b8eaSSimon J. Gerraty fprintf(stderr,
108eb12b8eaSSimon J. Gerraty "skipping to next fingerprint\n");
109eb12b8eaSSimon J. Gerraty }
110eb12b8eaSSimon J. Gerraty ;
111eb12b8eaSSimon J. Gerraty
112eb12b8eaSSimon J. Gerraty attributes: /* empty */
113eb12b8eaSSimon J. Gerraty | attributes flag
114eb12b8eaSSimon J. Gerraty | attributes attr
115eb12b8eaSSimon J. Gerraty ;
116eb12b8eaSSimon J. Gerraty
117eb12b8eaSSimon J. Gerraty attr: STRING EQ STRING
118eb12b8eaSSimon J. Gerraty {
119eb12b8eaSSimon J. Gerraty int fptype;
120eb12b8eaSSimon J. Gerraty
121eb12b8eaSSimon J. Gerraty fptype = get_fingerprint_type($1);
122eb12b8eaSSimon J. Gerraty
123eb12b8eaSSimon J. Gerraty /*
124eb12b8eaSSimon J. Gerraty * There's only one attribute we care about
125eb12b8eaSSimon J. Gerraty */
126eb12b8eaSSimon J. Gerraty if (fingerprint_table[fptype].fp_size) {
127eb12b8eaSSimon J. Gerraty strlcpy(params->fp_type, $1, sizeof(params->fp_type));
128eb12b8eaSSimon J. Gerraty if (convert($3, fingerprint_table[fptype].fp_size,
129eb12b8eaSSimon J. Gerraty params->fingerprint) < 0) {
130eb12b8eaSSimon J. Gerraty yyerror("bad fingerprint");
131eb12b8eaSSimon J. Gerraty YYERROR;
132eb12b8eaSSimon J. Gerraty }
133eb12b8eaSSimon J. Gerraty } else if (strcmp($1, "label") == 0) {
134eb12b8eaSSimon J. Gerraty static int warned_labels = 0;
135eb12b8eaSSimon J. Gerraty
136eb12b8eaSSimon J. Gerraty #ifdef VERIEXEC_LABEL
137eb12b8eaSSimon J. Gerraty strlcpy(lparams.label, $3, sizeof(lparams.label));
138eb12b8eaSSimon J. Gerraty VERBOSE(3, ("version=%d label=%s\n", VeriexecVersion,
139eb12b8eaSSimon J. Gerraty lparams.label));
140eb12b8eaSSimon J. Gerraty if (VeriexecVersion > 1) {
141eb12b8eaSSimon J. Gerraty params->flags |= VERIEXEC_LABEL;
142eb12b8eaSSimon J. Gerraty } else
143eb12b8eaSSimon J. Gerraty #endif
144eb12b8eaSSimon J. Gerraty if (!warned_labels) {
145eb12b8eaSSimon J. Gerraty warnx("ignoring labels");
146eb12b8eaSSimon J. Gerraty warned_labels = 1;
147eb12b8eaSSimon J. Gerraty }
148eb12b8eaSSimon J. Gerraty } else if (strcmp($1, "mode") == 0) {
149eb12b8eaSSimon J. Gerraty fmode = (int)strtol($3, NULL, 8);
150eb12b8eaSSimon J. Gerraty }
151eb12b8eaSSimon J. Gerraty };
152eb12b8eaSSimon J. Gerraty
153eb12b8eaSSimon J. Gerraty flag: STRING
154eb12b8eaSSimon J. Gerraty {
155eb12b8eaSSimon J. Gerraty /*
156eb12b8eaSSimon J. Gerraty * indirect only matters if the interpreter itself is not
157eb12b8eaSSimon J. Gerraty * executable.
158eb12b8eaSSimon J. Gerraty */
159eb12b8eaSSimon J. Gerraty if (!strcmp($1, "indirect")) {
160eb12b8eaSSimon J. Gerraty params->flags |= VERIEXEC_INDIRECT;
161eb12b8eaSSimon J. Gerraty } else if (!strcmp($1, "no_ptrace")) {
162eb12b8eaSSimon J. Gerraty params->flags |= VERIEXEC_NOTRACE;
163eb12b8eaSSimon J. Gerraty } else if (!strcmp($1, "trusted")) {
164eb12b8eaSSimon J. Gerraty params->flags |= VERIEXEC_TRUSTED;
165eb12b8eaSSimon J. Gerraty } else if (!strcmp($1, "no_fips")) {
166eb12b8eaSSimon J. Gerraty #ifdef VERIEXEC_NOFIPS
167eb12b8eaSSimon J. Gerraty params->flags |= VERIEXEC_NOFIPS;
168eb12b8eaSSimon J. Gerraty #endif
169eb12b8eaSSimon J. Gerraty }
170eb12b8eaSSimon J. Gerraty }
171eb12b8eaSSimon J. Gerraty ;
172eb12b8eaSSimon J. Gerraty
173eb12b8eaSSimon J. Gerraty path: PATH
174eb12b8eaSSimon J. Gerraty {
175eb12b8eaSSimon J. Gerraty if (strlen($1) >= MAXPATHLEN) {
176eb12b8eaSSimon J. Gerraty yyerror("Path >= MAXPATHLEN");
177eb12b8eaSSimon J. Gerraty YYERROR;
178eb12b8eaSSimon J. Gerraty }
179eb12b8eaSSimon J. Gerraty /*
180eb12b8eaSSimon J. Gerraty * The majority of files in the manifest are relative
181eb12b8eaSSimon J. Gerraty * to the package mount point, but we want absolute paths.
182eb12b8eaSSimon J. Gerraty * Prepending '/' is actually all we need.
183eb12b8eaSSimon J. Gerraty */
184eb12b8eaSSimon J. Gerraty if (snprintf(params->file, sizeof(params->file), "%s%s%s",
185eb12b8eaSSimon J. Gerraty Cdir ? Cdir : "",
186eb12b8eaSSimon J. Gerraty ($1[0] == '/') ? "" : "/",
187eb12b8eaSSimon J. Gerraty $1) >= (int)sizeof(params->file)) {
188eb12b8eaSSimon J. Gerraty errx(EX_DATAERR, "cannot form pathname");
189eb12b8eaSSimon J. Gerraty }
190eb12b8eaSSimon J. Gerraty params->flags = 0;
191eb12b8eaSSimon J. Gerraty fmode = -1; /* unknown */
192eb12b8eaSSimon J. Gerraty };
193eb12b8eaSSimon J. Gerraty
194eb12b8eaSSimon J. Gerraty eol: EOL
195eb12b8eaSSimon J. Gerraty {
196eb12b8eaSSimon J. Gerraty if (!YYRECOVERING()) { /* Don't do the ioctl if we saw an error */
197eb12b8eaSSimon J. Gerraty do_ioctl();
198eb12b8eaSSimon J. Gerraty }
199eb12b8eaSSimon J. Gerraty params->fp_type[0] = '\0'; /* invalidate it */
200eb12b8eaSSimon J. Gerraty };
201eb12b8eaSSimon J. Gerraty
202eb12b8eaSSimon J. Gerraty %%
203eb12b8eaSSimon J. Gerraty
204eb12b8eaSSimon J. Gerraty void
205eb12b8eaSSimon J. Gerraty manifest_parser_init(void)
206eb12b8eaSSimon J. Gerraty {
207eb12b8eaSSimon J. Gerraty params->fp_type[0] = '\0'; /* invalidate it */
208eb12b8eaSSimon J. Gerraty }
209eb12b8eaSSimon J. Gerraty
210eb12b8eaSSimon J. Gerraty int
get_fingerprint_type(const char * fp_type)211eb12b8eaSSimon J. Gerraty get_fingerprint_type(const char *fp_type)
212eb12b8eaSSimon J. Gerraty {
213eb12b8eaSSimon J. Gerraty int i;
214eb12b8eaSSimon J. Gerraty
215eb12b8eaSSimon J. Gerraty for (i = 0; fingerprint_table[i].fp_type; i++)
216eb12b8eaSSimon J. Gerraty if (!strcmp(fp_type, fingerprint_table[i].fp_type))
217eb12b8eaSSimon J. Gerraty break;
218eb12b8eaSSimon J. Gerraty
219eb12b8eaSSimon J. Gerraty return (i);
220eb12b8eaSSimon J. Gerraty }
221eb12b8eaSSimon J. Gerraty
222eb12b8eaSSimon J. Gerraty /*
223eb12b8eaSSimon J. Gerraty * Convert: takes the hexadecimal string pointed to by fp and converts
224eb12b8eaSSimon J. Gerraty * it to a "count" byte binary number which is stored in the array pointed to
225eb12b8eaSSimon J. Gerraty * by out. Returns -1 if the conversion fails.
226eb12b8eaSSimon J. Gerraty */
227eb12b8eaSSimon J. Gerraty static int
convert(char * fp,unsigned int count,unsigned char * out)228eb12b8eaSSimon J. Gerraty convert(char *fp, unsigned int count, unsigned char *out)
229eb12b8eaSSimon J. Gerraty {
230eb12b8eaSSimon J. Gerraty unsigned int i;
231eb12b8eaSSimon J. Gerraty int value;
232eb12b8eaSSimon J. Gerraty
233eb12b8eaSSimon J. Gerraty for (i = 0; i < count; i++) {
234eb12b8eaSSimon J. Gerraty value = 0;
235eb12b8eaSSimon J. Gerraty if (isdigit(fp[i * 2]))
236eb12b8eaSSimon J. Gerraty value += fp[i * 2] - '0';
237eb12b8eaSSimon J. Gerraty else if (isxdigit(fp[i * 2]))
238eb12b8eaSSimon J. Gerraty value += 10 + tolower(fp[i * 2]) - 'a';
239eb12b8eaSSimon J. Gerraty else
240eb12b8eaSSimon J. Gerraty return (-1);
241eb12b8eaSSimon J. Gerraty value <<= 4;
242eb12b8eaSSimon J. Gerraty if (isdigit(fp[i * 2 + 1]))
243eb12b8eaSSimon J. Gerraty value += fp[i * 2 + 1] - '0';
244eb12b8eaSSimon J. Gerraty else if (isxdigit(fp[i * 2 + 1]))
245eb12b8eaSSimon J. Gerraty value += 10 + tolower(fp[i * 2 + 1]) - 'a';
246eb12b8eaSSimon J. Gerraty else
247eb12b8eaSSimon J. Gerraty return (-1);
248eb12b8eaSSimon J. Gerraty out[i] = value;
249eb12b8eaSSimon J. Gerraty }
250eb12b8eaSSimon J. Gerraty
251eb12b8eaSSimon J. Gerraty return (i);
252eb12b8eaSSimon J. Gerraty }
253eb12b8eaSSimon J. Gerraty
254eb12b8eaSSimon J. Gerraty /*
255eb12b8eaSSimon J. Gerraty * Perform the load of the fingerprint. Assumes that the fingerprint
256eb12b8eaSSimon J. Gerraty * pseudo-device is opened and the file handle is in fd.
257eb12b8eaSSimon J. Gerraty */
258eb12b8eaSSimon J. Gerraty static void
do_ioctl(void)259eb12b8eaSSimon J. Gerraty do_ioctl(void)
260eb12b8eaSSimon J. Gerraty {
261eb12b8eaSSimon J. Gerraty struct stat st;
262eb12b8eaSSimon J. Gerraty
263eb12b8eaSSimon J. Gerraty if (params->fp_type[0] == '\0') {
264eb12b8eaSSimon J. Gerraty VERBOSE(1,("skipping %s\n", params->file));
265eb12b8eaSSimon J. Gerraty return;
266eb12b8eaSSimon J. Gerraty }
267eb12b8eaSSimon J. Gerraty
268eb12b8eaSSimon J. Gerraty /*
269eb12b8eaSSimon J. Gerraty * See if the path is executable, if not put it on the FILE list.
270eb12b8eaSSimon J. Gerraty */
271eb12b8eaSSimon J. Gerraty if (fmode > 0) {
272eb12b8eaSSimon J. Gerraty if (!(fmode & (S_IXUSR|S_IXGRP|S_IXOTH))) {
273eb12b8eaSSimon J. Gerraty params->flags |= VERIEXEC_FILE;
274eb12b8eaSSimon J. Gerraty }
275eb12b8eaSSimon J. Gerraty } else if (stat(params->file, &st) == 0) {
276eb12b8eaSSimon J. Gerraty if (!(st.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH))) {
277eb12b8eaSSimon J. Gerraty params->flags |= VERIEXEC_FILE;
278eb12b8eaSSimon J. Gerraty }
279eb12b8eaSSimon J. Gerraty }
280eb12b8eaSSimon J. Gerraty /*
281eb12b8eaSSimon J. Gerraty * We may be forcing some flags...
282eb12b8eaSSimon J. Gerraty */
283eb12b8eaSSimon J. Gerraty params->flags |= ForceFlags;
284eb12b8eaSSimon J. Gerraty VERBOSE(1, ("loading %s for %s %s flags=%#x\n",
285eb12b8eaSSimon J. Gerraty params->fp_type,
286eb12b8eaSSimon J. Gerraty (params->flags == VERIEXEC_FILE) ? "file" : "executable",
287eb12b8eaSSimon J. Gerraty params->file, params->flags));
288eb12b8eaSSimon J. Gerraty
289eb12b8eaSSimon J. Gerraty #ifdef VERIEXEC_LABEL
290eb12b8eaSSimon J. Gerraty if (params->flags & VERIEXEC_LABEL) {
291eb12b8eaSSimon J. Gerraty if (ioctl(dev_fd, VERIEXEC_LABEL_LOAD, &lparams) < 0)
292eb12b8eaSSimon J. Gerraty warn("cannot update veriexec label for %s",
293eb12b8eaSSimon J. Gerraty params->file);
294eb12b8eaSSimon J. Gerraty } else
295eb12b8eaSSimon J. Gerraty #endif
296eb12b8eaSSimon J. Gerraty if (ioctl(dev_fd, VERIEXEC_SIGNED_LOAD, params) < 0)
297eb12b8eaSSimon J. Gerraty warn("cannot update veriexec for %s", params->file);
298eb12b8eaSSimon J. Gerraty params->fp_type[0] = '\0';
299eb12b8eaSSimon J. Gerraty }
300