]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libsecureboot/pass_manifest.c
Implement pci_enable_msi() and pci_disable_msi() in the LinuxKPI.
[FreeBSD/FreeBSD.git] / lib / libsecureboot / pass_manifest.c
1 /*-
2  * Copyright (c) 2019 Stormshield.
3  * Copyright (c) 2019 Semihalf.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
18  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
22  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
23  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24  * POSSIBILITY OF SUCH DAMAGE.
25  *
26  * $FreeBSD$
27  */
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
30
31 #include <sys/stat.h>
32
33 #include "libsecureboot-priv.h"
34 #include <verify_file.h>
35
36 /*
37  * Values to pass to kernel by envs.
38  */
39 static char manifest_path[MAXPATHLEN];
40 static char manifest_prefix[MAXPATHLEN];
41 static char manifest_hash[2 * br_sha256_SIZE + 2];
42 static int manifest_present = 0;
43
44 /*
45  * Verify and pass manifest path and digest to kernel through envs.
46  * The paths in manifest can be either absolute,
47  * or "prefix", if exists will be added to the ones that are not.
48  */
49 int
50 pass_manifest(const char *path, const char *prefix)
51 {
52         char *content;
53         struct stat st;
54         unsigned char digest[br_sha256_SIZE];
55         const br_hash_class *md;
56         br_hash_compat_context ctx;
57         int rc;
58
59         content = NULL;
60         md = &br_sha256_vtable;
61
62         if (strnlen(path, MAXPATHLEN) == MAXPATHLEN ||
63             strnlen(prefix, MAXPATHLEN) == MAXPATHLEN)
64                 return (EINVAL);
65
66         rc = stat(path, &st);
67         if (rc != 0)
68                 goto out;
69
70         if (!S_ISREG(st.st_mode)) {
71                 rc = EINVAL;
72                 goto out;
73         }
74
75         rc = is_verified(&st);
76
77         if (rc != VE_NOT_CHECKED && rc != VE_VERIFIED) {
78                 rc = EPERM;
79                 goto out;
80         }
81
82         if (rc == VE_VERIFIED)
83                 content = read_file(path, NULL);
84         else
85                 content = (char *)verify_signed(path, VEF_VERBOSE);
86
87         if (content == NULL) {
88                 add_verify_status(&st, VE_FINGERPRINT_WRONG);
89                 rc = EIO;
90                 goto out;
91         }
92
93         add_verify_status(&st, VE_VERIFIED);
94
95         md->init(&ctx.vtable);
96         md->update(&ctx.vtable, content, st.st_size);
97         md->out(&ctx.vtable, digest);
98
99         if (prefix == NULL)
100                 manifest_prefix[0] = '\0';
101         else
102                 strcpy(manifest_prefix, prefix);
103
104         strcpy(manifest_path, path);
105
106         hexdigest(manifest_hash, 2 * br_sha256_SIZE + 2,
107             digest, br_sha256_SIZE);
108         manifest_hash[2*br_sha256_SIZE] = '\0';
109
110         manifest_present = 1;
111         rc = 0;
112
113 out:
114         if (content != NULL)
115                 free(content);
116
117         return (rc);
118 }
119
120 /*
121  * Set appropriate envs to inform kernel about manifest location and digest.
122  * This should be called right before boot so that envs can't be replaced.
123  */
124 int
125 pass_manifest_export_envs()
126 {
127         int rc;
128
129         /* If we have nothing to pass make sure that envs are empty. */
130         if (!manifest_present) {
131                 unsetenv("veriexec.manifest_path");
132                 unsetenv("veriexec.manifest_hash");
133                 unsetenv("veriexec.manifest_prefix");
134                 return (0);
135         }
136
137         rc = setenv("veriexec.manifest_path", manifest_path, 1);
138         if (rc != 0)
139                 return (rc);
140
141         rc = setenv("veriexec.manifest_hash", manifest_hash, 1);
142         if (rc != 0) {
143                 unsetenv("veriexec.manifest_path");
144                 return (rc);
145         }
146
147         if (manifest_prefix[0] != '\0')
148                 rc = setenv("veriexec.manifest_prefix", manifest_prefix, 1);
149
150         return (rc);
151 }
152