]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libsecureboot/pass_manifest.c
libc(bt_utils.c): fix "contiguous" spelling
[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 #include <sys/cdefs.h>
27 #include <sys/stat.h>
28
29 #include "libsecureboot-priv.h"
30 #include <verify_file.h>
31
32 /*
33  * Values to pass to kernel by envs.
34  */
35 static char manifest_path[MAXPATHLEN];
36 static char manifest_prefix[MAXPATHLEN];
37 static char manifest_hash[2 * br_sha256_SIZE + 2];
38 static int manifest_present = 0;
39
40 /*
41  * Verify and pass manifest path and digest to kernel through envs.
42  * The paths in manifest can be either absolute,
43  * or "prefix", if exists will be added to the ones that are not.
44  */
45 int
46 pass_manifest(const char *path, const char *prefix)
47 {
48         char *content;
49         struct stat st;
50         unsigned char digest[br_sha256_SIZE];
51         const br_hash_class *md;
52         br_hash_compat_context ctx;
53         int rc;
54
55         content = NULL;
56         md = &br_sha256_vtable;
57
58         if (strnlen(path, MAXPATHLEN) == MAXPATHLEN ||
59             strnlen(prefix, MAXPATHLEN) == MAXPATHLEN)
60                 return (EINVAL);
61
62         rc = stat(path, &st);
63         if (rc != 0)
64                 goto out;
65
66         if (!S_ISREG(st.st_mode)) {
67                 rc = EINVAL;
68                 goto out;
69         }
70
71         rc = is_verified(&st);
72
73         if (rc != VE_NOT_CHECKED && rc != VE_VERIFIED) {
74                 rc = EPERM;
75                 goto out;
76         }
77
78         if (rc == VE_VERIFIED)
79                 content = read_file(path, NULL);
80         else
81                 content = (char *)verify_signed(path, VEF_VERBOSE);
82
83         if (content == NULL) {
84                 add_verify_status(&st, VE_FINGERPRINT_WRONG);
85                 rc = EIO;
86                 goto out;
87         }
88
89         add_verify_status(&st, VE_VERIFIED);
90
91         md->init(&ctx.vtable);
92         md->update(&ctx.vtable, content, st.st_size);
93         md->out(&ctx.vtable, digest);
94
95         if (prefix == NULL)
96                 manifest_prefix[0] = '\0';
97         else
98                 strcpy(manifest_prefix, prefix);
99
100         strcpy(manifest_path, path);
101
102         hexdigest(manifest_hash, 2 * br_sha256_SIZE + 2,
103             digest, br_sha256_SIZE);
104         manifest_hash[2*br_sha256_SIZE] = '\0';
105
106         manifest_present = 1;
107         rc = 0;
108
109 out:
110         if (content != NULL)
111                 free(content);
112
113         return (rc);
114 }
115
116 /*
117  * Set appropriate envs to inform kernel about manifest location and digest.
118  * This should be called right before boot so that envs can't be replaced.
119  */
120 int
121 pass_manifest_export_envs()
122 {
123         int rc;
124
125         /* If we have nothing to pass make sure that envs are empty. */
126         if (!manifest_present) {
127                 unsetenv("veriexec.manifest_path");
128                 unsetenv("veriexec.manifest_hash");
129                 unsetenv("veriexec.manifest_prefix");
130                 return (0);
131         }
132
133         rc = setenv("veriexec.manifest_path", manifest_path, 1);
134         if (rc != 0)
135                 return (rc);
136
137         rc = setenv("veriexec.manifest_hash", manifest_hash, 1);
138         if (rc != 0) {
139                 unsetenv("veriexec.manifest_path");
140                 return (rc);
141         }
142
143         if (manifest_prefix[0] != '\0')
144                 rc = setenv("veriexec.manifest_prefix", manifest_prefix, 1);
145
146         return (rc);
147 }
148