1*13ea0450SMarcin Wojtas /*-
2*13ea0450SMarcin Wojtas * Copyright (c) 2019 Stormshield.
3*13ea0450SMarcin Wojtas * Copyright (c) 2019 Semihalf.
4*13ea0450SMarcin Wojtas *
5*13ea0450SMarcin Wojtas * Redistribution and use in source and binary forms, with or without
6*13ea0450SMarcin Wojtas * modification, are permitted provided that the following conditions
7*13ea0450SMarcin Wojtas * are met:
8*13ea0450SMarcin Wojtas * 1. Redistributions of source code must retain the above copyright
9*13ea0450SMarcin Wojtas * notice, this list of conditions and the following disclaimer.
10*13ea0450SMarcin Wojtas * 2. Redistributions in binary form must reproduce the above copyright
11*13ea0450SMarcin Wojtas * notice, this list of conditions and the following disclaimer in the
12*13ea0450SMarcin Wojtas * documentation and/or other materials provided with the distribution.
13*13ea0450SMarcin Wojtas *
14*13ea0450SMarcin Wojtas * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15*13ea0450SMarcin Wojtas * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16*13ea0450SMarcin Wojtas * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17*13ea0450SMarcin Wojtas * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
18*13ea0450SMarcin Wojtas * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19*13ea0450SMarcin Wojtas * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20*13ea0450SMarcin Wojtas * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21*13ea0450SMarcin Wojtas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
22*13ea0450SMarcin Wojtas * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
23*13ea0450SMarcin Wojtas * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24*13ea0450SMarcin Wojtas * POSSIBILITY OF SUCH DAMAGE.
25*13ea0450SMarcin Wojtas */
26*13ea0450SMarcin Wojtas
27*13ea0450SMarcin Wojtas #include <sys/cdefs.h>
28*13ea0450SMarcin Wojtas #include <stand.h>
29*13ea0450SMarcin Wojtas #include <string.h>
30*13ea0450SMarcin Wojtas
31*13ea0450SMarcin Wojtas #include <efi.h>
32*13ea0450SMarcin Wojtas #include <efilib.h>
33*13ea0450SMarcin Wojtas #include <Guid/ImageAuthentication.h>
34*13ea0450SMarcin Wojtas
35*13ea0450SMarcin Wojtas #define NEED_BRSSL_H
36*13ea0450SMarcin Wojtas #include "../libsecureboot-priv.h"
37*13ea0450SMarcin Wojtas #include <brssl.h>
38*13ea0450SMarcin Wojtas
39*13ea0450SMarcin Wojtas static EFI_GUID ImageSecurityDatabaseGUID = EFI_IMAGE_SECURITY_DATABASE_GUID;
40*13ea0450SMarcin Wojtas
41*13ea0450SMarcin Wojtas static EFI_GUID efiCertX509GUID = EFI_CERT_X509_GUID;
42*13ea0450SMarcin Wojtas static EFI_GUID efiCertX509Sha256GUID = EFI_CERT_X509_SHA256_GUID;
43*13ea0450SMarcin Wojtas static EFI_GUID efiCertX509Sha384GUID = EFI_CERT_X509_SHA384_GUID;
44*13ea0450SMarcin Wojtas static EFI_GUID efiCertX509Sha5122UID = EFI_CERT_X509_SHA512_GUID;
45*13ea0450SMarcin Wojtas
46*13ea0450SMarcin Wojtas /*
47*13ea0450SMarcin Wojtas * Check if Secure Boot is enabled in firmware.
48*13ea0450SMarcin Wojtas * We evaluate two variables - Secure Boot and Setup Mode.
49*13ea0450SMarcin Wojtas * Secure Boot is enforced only if the first one equals 1 and the other 0.
50*13ea0450SMarcin Wojtas */
51*13ea0450SMarcin Wojtas int
efi_secure_boot_enabled(void)52*13ea0450SMarcin Wojtas efi_secure_boot_enabled(void)
53*13ea0450SMarcin Wojtas {
54*13ea0450SMarcin Wojtas UINT8 SecureBoot;
55*13ea0450SMarcin Wojtas UINT8 SetupMode;
56*13ea0450SMarcin Wojtas size_t length;
57*13ea0450SMarcin Wojtas EFI_STATUS status;
58*13ea0450SMarcin Wojtas
59*13ea0450SMarcin Wojtas length = sizeof(SecureBoot);
60*13ea0450SMarcin Wojtas status = efi_global_getenv("SecureBoot", &SecureBoot, &length);
61*13ea0450SMarcin Wojtas if (status != EFI_SUCCESS) {
62*13ea0450SMarcin Wojtas if (status == EFI_NOT_FOUND)
63*13ea0450SMarcin Wojtas return (0);
64*13ea0450SMarcin Wojtas
65*13ea0450SMarcin Wojtas printf("Failed to read \"SecureBoot\" variable\n");
66*13ea0450SMarcin Wojtas return (-efi_status_to_errno(status));
67*13ea0450SMarcin Wojtas }
68*13ea0450SMarcin Wojtas
69*13ea0450SMarcin Wojtas length = sizeof(SetupMode);
70*13ea0450SMarcin Wojtas status = efi_global_getenv("SetupMode", &SetupMode, &length);
71*13ea0450SMarcin Wojtas if (status != EFI_SUCCESS)
72*13ea0450SMarcin Wojtas SetupMode = 0;
73*13ea0450SMarcin Wojtas
74*13ea0450SMarcin Wojtas printf(" SecureBoot: %d, SetupMode: %d\n", SecureBoot, SetupMode);
75*13ea0450SMarcin Wojtas
76*13ea0450SMarcin Wojtas return (SecureBoot == 1 && SetupMode == 0);
77*13ea0450SMarcin Wojtas }
78*13ea0450SMarcin Wojtas
79*13ea0450SMarcin Wojtas /*
80*13ea0450SMarcin Wojtas * Iterate through UEFI variable and extract X509 certificates from it.
81*13ea0450SMarcin Wojtas * The EFI_* structures and related guids are defined in UEFI standard.
82*13ea0450SMarcin Wojtas */
83*13ea0450SMarcin Wojtas static br_x509_certificate*
efi_get_certs(const char * name,size_t * count)84*13ea0450SMarcin Wojtas efi_get_certs(const char *name, size_t *count)
85*13ea0450SMarcin Wojtas {
86*13ea0450SMarcin Wojtas br_x509_certificate *certs;
87*13ea0450SMarcin Wojtas UINT8 *database;
88*13ea0450SMarcin Wojtas EFI_SIGNATURE_LIST *list;
89*13ea0450SMarcin Wojtas EFI_SIGNATURE_DATA *entry;
90*13ea0450SMarcin Wojtas size_t db_size;
91*13ea0450SMarcin Wojtas ssize_t cert_count;
92*13ea0450SMarcin Wojtas EFI_STATUS status;
93*13ea0450SMarcin Wojtas
94*13ea0450SMarcin Wojtas database = NULL;
95*13ea0450SMarcin Wojtas certs = NULL;
96*13ea0450SMarcin Wojtas db_size = 0;
97*13ea0450SMarcin Wojtas cert_count = 0;
98*13ea0450SMarcin Wojtas
99*13ea0450SMarcin Wojtas /*
100*13ea0450SMarcin Wojtas * Read variable length and allocate memory for it
101*13ea0450SMarcin Wojtas */
102*13ea0450SMarcin Wojtas status = efi_getenv(&ImageSecurityDatabaseGUID, name, database, &db_size);
103*13ea0450SMarcin Wojtas if (status != EFI_BUFFER_TOO_SMALL)
104*13ea0450SMarcin Wojtas return (NULL);
105*13ea0450SMarcin Wojtas
106*13ea0450SMarcin Wojtas database = malloc(db_size);
107*13ea0450SMarcin Wojtas if (database == NULL)
108*13ea0450SMarcin Wojtas return (NULL);
109*13ea0450SMarcin Wojtas
110*13ea0450SMarcin Wojtas status = efi_getenv(&ImageSecurityDatabaseGUID, name, database, &db_size);
111*13ea0450SMarcin Wojtas if (status != EFI_SUCCESS)
112*13ea0450SMarcin Wojtas goto fail;
113*13ea0450SMarcin Wojtas
114*13ea0450SMarcin Wojtas for (list = (EFI_SIGNATURE_LIST*) database;
115*13ea0450SMarcin Wojtas db_size >= list->SignatureListSize && db_size > 0;
116*13ea0450SMarcin Wojtas db_size -= list->SignatureListSize,
117*13ea0450SMarcin Wojtas list = (EFI_SIGNATURE_LIST*)
118*13ea0450SMarcin Wojtas ((UINT8*)list + list->SignatureListSize)) {
119*13ea0450SMarcin Wojtas
120*13ea0450SMarcin Wojtas /* We are only interested in entries containing X509 certs. */
121*13ea0450SMarcin Wojtas if (memcmp(&efiCertX509GUID,
122*13ea0450SMarcin Wojtas &list->SignatureType,
123*13ea0450SMarcin Wojtas sizeof(EFI_GUID)) != 0) {
124*13ea0450SMarcin Wojtas continue;
125*13ea0450SMarcin Wojtas }
126*13ea0450SMarcin Wojtas
127*13ea0450SMarcin Wojtas entry = (EFI_SIGNATURE_DATA*)
128*13ea0450SMarcin Wojtas ((UINT8*)list +
129*13ea0450SMarcin Wojtas sizeof(EFI_SIGNATURE_LIST) +
130*13ea0450SMarcin Wojtas list->SignatureHeaderSize);
131*13ea0450SMarcin Wojtas
132*13ea0450SMarcin Wojtas certs = realloc(certs,
133*13ea0450SMarcin Wojtas (cert_count + 1) * sizeof(br_x509_certificate));
134*13ea0450SMarcin Wojtas if (certs == NULL) {
135*13ea0450SMarcin Wojtas cert_count = 0;
136*13ea0450SMarcin Wojtas goto fail;
137*13ea0450SMarcin Wojtas }
138*13ea0450SMarcin Wojtas
139*13ea0450SMarcin Wojtas certs[cert_count].data_len = list->SignatureSize - sizeof(EFI_GUID);
140*13ea0450SMarcin Wojtas certs[cert_count].data = malloc(certs[cert_count].data_len);
141*13ea0450SMarcin Wojtas if (certs[cert_count].data == NULL)
142*13ea0450SMarcin Wojtas goto fail;
143*13ea0450SMarcin Wojtas
144*13ea0450SMarcin Wojtas memcpy(certs[cert_count].data,
145*13ea0450SMarcin Wojtas entry->SignatureData,
146*13ea0450SMarcin Wojtas certs[cert_count].data_len);
147*13ea0450SMarcin Wojtas
148*13ea0450SMarcin Wojtas cert_count++;
149*13ea0450SMarcin Wojtas }
150*13ea0450SMarcin Wojtas
151*13ea0450SMarcin Wojtas *count = cert_count;
152*13ea0450SMarcin Wojtas
153*13ea0450SMarcin Wojtas xfree(database);
154*13ea0450SMarcin Wojtas return (certs);
155*13ea0450SMarcin Wojtas
156*13ea0450SMarcin Wojtas fail:
157*13ea0450SMarcin Wojtas free_certificates(certs, cert_count);
158*13ea0450SMarcin Wojtas xfree(database);
159*13ea0450SMarcin Wojtas return (NULL);
160*13ea0450SMarcin Wojtas
161*13ea0450SMarcin Wojtas }
162*13ea0450SMarcin Wojtas
163*13ea0450SMarcin Wojtas /*
164*13ea0450SMarcin Wojtas * Extract digests from UEFI "dbx" variable.
165*13ea0450SMarcin Wojtas * UEFI standard specifies three types of digest - sha256, sha386, sha512.
166*13ea0450SMarcin Wojtas */
167*13ea0450SMarcin Wojtas hash_data*
efi_get_forbidden_digests(size_t * count)168*13ea0450SMarcin Wojtas efi_get_forbidden_digests(size_t *count)
169*13ea0450SMarcin Wojtas {
170*13ea0450SMarcin Wojtas UINT8 *database;
171*13ea0450SMarcin Wojtas hash_data *digests;
172*13ea0450SMarcin Wojtas EFI_SIGNATURE_LIST *list;
173*13ea0450SMarcin Wojtas EFI_SIGNATURE_DATA *entry;
174*13ea0450SMarcin Wojtas size_t db_size, header_size, hash_size;
175*13ea0450SMarcin Wojtas int digest_count, entry_count;
176*13ea0450SMarcin Wojtas EFI_STATUS status;
177*13ea0450SMarcin Wojtas
178*13ea0450SMarcin Wojtas db_size = 0;
179*13ea0450SMarcin Wojtas digest_count = 0;
180*13ea0450SMarcin Wojtas database = NULL;
181*13ea0450SMarcin Wojtas digests = NULL;
182*13ea0450SMarcin Wojtas
183*13ea0450SMarcin Wojtas status = efi_getenv(&ImageSecurityDatabaseGUID, "dbx", database, &db_size);
184*13ea0450SMarcin Wojtas if (status != EFI_BUFFER_TOO_SMALL)
185*13ea0450SMarcin Wojtas return (NULL);
186*13ea0450SMarcin Wojtas
187*13ea0450SMarcin Wojtas database = malloc(db_size);
188*13ea0450SMarcin Wojtas if (database == NULL)
189*13ea0450SMarcin Wojtas return (NULL);
190*13ea0450SMarcin Wojtas
191*13ea0450SMarcin Wojtas status = efi_getenv(&ImageSecurityDatabaseGUID, "dbx", database, &db_size);
192*13ea0450SMarcin Wojtas if (status != EFI_SUCCESS)
193*13ea0450SMarcin Wojtas goto fail;
194*13ea0450SMarcin Wojtas
195*13ea0450SMarcin Wojtas
196*13ea0450SMarcin Wojtas for (list = (EFI_SIGNATURE_LIST*) database;
197*13ea0450SMarcin Wojtas db_size >= list->SignatureListSize && db_size > 0;
198*13ea0450SMarcin Wojtas db_size -= list->SignatureListSize,
199*13ea0450SMarcin Wojtas list = (EFI_SIGNATURE_LIST*)
200*13ea0450SMarcin Wojtas ((UINT8*)list + list->SignatureListSize)) {
201*13ea0450SMarcin Wojtas
202*13ea0450SMarcin Wojtas /* We are only interested in entries that contain digests. */
203*13ea0450SMarcin Wojtas if (memcmp(&efiCertX509Sha256GUID, &list->SignatureType,
204*13ea0450SMarcin Wojtas sizeof(EFI_GUID)) == 0) {
205*13ea0450SMarcin Wojtas hash_size = br_sha256_SIZE;
206*13ea0450SMarcin Wojtas } else if (memcmp(&efiCertX509Sha384GUID, &list->SignatureType,
207*13ea0450SMarcin Wojtas sizeof(EFI_GUID)) == 0) {
208*13ea0450SMarcin Wojtas hash_size = br_sha384_SIZE;
209*13ea0450SMarcin Wojtas } else if (memcmp(&efiCertX509Sha5122UID, &list->SignatureType,
210*13ea0450SMarcin Wojtas sizeof(EFI_GUID)) == 0) {
211*13ea0450SMarcin Wojtas hash_size = br_sha512_SIZE;
212*13ea0450SMarcin Wojtas } else {
213*13ea0450SMarcin Wojtas continue;
214*13ea0450SMarcin Wojtas }
215*13ea0450SMarcin Wojtas
216*13ea0450SMarcin Wojtas /*
217*13ea0450SMarcin Wojtas * A single entry can have multiple digests
218*13ea0450SMarcin Wojtas * of the same type for some reason.
219*13ea0450SMarcin Wojtas */
220*13ea0450SMarcin Wojtas header_size = sizeof(EFI_SIGNATURE_LIST) + list->SignatureHeaderSize;
221*13ea0450SMarcin Wojtas
222*13ea0450SMarcin Wojtas /* Calculate the number of entries basing on structure size */
223*13ea0450SMarcin Wojtas entry_count = list->SignatureListSize - header_size;
224*13ea0450SMarcin Wojtas entry_count /= list->SignatureSize;
225*13ea0450SMarcin Wojtas entry = (EFI_SIGNATURE_DATA*)((UINT8*)list + header_size);
226*13ea0450SMarcin Wojtas while (entry_count-- > 0) {
227*13ea0450SMarcin Wojtas digests = realloc(digests,
228*13ea0450SMarcin Wojtas (digest_count + 1) * sizeof(hash_data));
229*13ea0450SMarcin Wojtas if (digests == NULL) {
230*13ea0450SMarcin Wojtas digest_count = 0;
231*13ea0450SMarcin Wojtas goto fail;
232*13ea0450SMarcin Wojtas }
233*13ea0450SMarcin Wojtas
234*13ea0450SMarcin Wojtas digests[digest_count].data = malloc(hash_size);
235*13ea0450SMarcin Wojtas if (digests[digest_count].data == NULL)
236*13ea0450SMarcin Wojtas goto fail;
237*13ea0450SMarcin Wojtas
238*13ea0450SMarcin Wojtas memcpy(digests[digest_count].data,
239*13ea0450SMarcin Wojtas entry->SignatureData,
240*13ea0450SMarcin Wojtas hash_size);
241*13ea0450SMarcin Wojtas digests[digest_count].hash_size = hash_size;
242*13ea0450SMarcin Wojtas
243*13ea0450SMarcin Wojtas entry = (EFI_SIGNATURE_DATA*)(entry + list->SignatureSize);
244*13ea0450SMarcin Wojtas digest_count++;
245*13ea0450SMarcin Wojtas }
246*13ea0450SMarcin Wojtas }
247*13ea0450SMarcin Wojtas xfree(database);
248*13ea0450SMarcin Wojtas if (count != NULL)
249*13ea0450SMarcin Wojtas *count = digest_count;
250*13ea0450SMarcin Wojtas
251*13ea0450SMarcin Wojtas return (digests);
252*13ea0450SMarcin Wojtas
253*13ea0450SMarcin Wojtas fail:
254*13ea0450SMarcin Wojtas while (digest_count--)
255*13ea0450SMarcin Wojtas xfree(digests[digest_count].data);
256*13ea0450SMarcin Wojtas
257*13ea0450SMarcin Wojtas xfree(database);
258*13ea0450SMarcin Wojtas xfree(digests);
259*13ea0450SMarcin Wojtas return (NULL);
260*13ea0450SMarcin Wojtas }
261*13ea0450SMarcin Wojtas
262*13ea0450SMarcin Wojtas /* Copy x509 certificates from db */
263*13ea0450SMarcin Wojtas br_x509_certificate*
efi_get_trusted_certs(size_t * count)264*13ea0450SMarcin Wojtas efi_get_trusted_certs(size_t *count)
265*13ea0450SMarcin Wojtas {
266*13ea0450SMarcin Wojtas return (efi_get_certs("db", count));
267*13ea0450SMarcin Wojtas }
268*13ea0450SMarcin Wojtas
269*13ea0450SMarcin Wojtas /* Copy forbidden certificates from dbx */
270*13ea0450SMarcin Wojtas br_x509_certificate*
efi_get_forbidden_certs(size_t * count)271*13ea0450SMarcin Wojtas efi_get_forbidden_certs(size_t *count)
272*13ea0450SMarcin Wojtas {
273*13ea0450SMarcin Wojtas return (efi_get_certs("dbx", count));
274*13ea0450SMarcin Wojtas }
275