2 * Copyright (c) 2019 Stormshield.
3 * Copyright (c) 2019 Semihalf.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
37 #include <Guid/ImageAuthentication.h>
40 #include "../libsecureboot-priv.h"
43 static EFI_GUID ImageSecurityDatabaseGUID = EFI_IMAGE_SECURITY_DATABASE_GUID;
45 static EFI_GUID efiCertX509GUID = EFI_CERT_X509_GUID;
46 static EFI_GUID efiCertX509Sha256GUID = EFI_CERT_X509_SHA256_GUID;
47 static EFI_GUID efiCertX509Sha384GUID = EFI_CERT_X509_SHA384_GUID;
48 static EFI_GUID efiCertX509Sha5122UID = EFI_CERT_X509_SHA512_GUID;
51 * Check if Secure Boot is enabled in firmware.
52 * We evaluate two variables - Secure Boot and Setup Mode.
53 * Secure Boot is enforced only if the first one equals 1 and the other 0.
56 efi_secure_boot_enabled(void)
63 length = sizeof(SecureBoot);
64 status = efi_global_getenv("SecureBoot", &SecureBoot, &length);
65 if (status != EFI_SUCCESS) {
66 if (status == EFI_NOT_FOUND)
69 printf("Failed to read \"SecureBoot\" variable\n");
70 return (-efi_status_to_errno(status));
73 length = sizeof(SetupMode);
74 status = efi_global_getenv("SetupMode", &SetupMode, &length);
75 if (status != EFI_SUCCESS)
78 printf(" SecureBoot: %d, SetupMode: %d\n", SecureBoot, SetupMode);
80 return (SecureBoot == 1 && SetupMode == 0);
84 * Iterate through UEFI variable and extract X509 certificates from it.
85 * The EFI_* structures and related guids are defined in UEFI standard.
87 static br_x509_certificate*
88 efi_get_certs(const char *name, size_t *count)
90 br_x509_certificate *certs;
92 EFI_SIGNATURE_LIST *list;
93 EFI_SIGNATURE_DATA *entry;
104 * Read variable length and allocate memory for it
106 status = efi_getenv(&ImageSecurityDatabaseGUID, name, database, &db_size);
107 if (status != EFI_BUFFER_TOO_SMALL)
110 database = malloc(db_size);
111 if (database == NULL)
114 status = efi_getenv(&ImageSecurityDatabaseGUID, name, database, &db_size);
115 if (status != EFI_SUCCESS)
118 for (list = (EFI_SIGNATURE_LIST*) database;
119 db_size >= list->SignatureListSize && db_size > 0;
120 db_size -= list->SignatureListSize,
121 list = (EFI_SIGNATURE_LIST*)
122 ((UINT8*)list + list->SignatureListSize)) {
124 /* We are only interested in entries containing X509 certs. */
125 if (memcmp(&efiCertX509GUID,
126 &list->SignatureType,
127 sizeof(EFI_GUID)) != 0) {
131 entry = (EFI_SIGNATURE_DATA*)
133 sizeof(EFI_SIGNATURE_LIST) +
134 list->SignatureHeaderSize);
136 certs = realloc(certs,
137 (cert_count + 1) * sizeof(br_x509_certificate));
143 certs[cert_count].data_len = list->SignatureSize - sizeof(EFI_GUID);
144 certs[cert_count].data = malloc(certs[cert_count].data_len);
145 if (certs[cert_count].data == NULL)
148 memcpy(certs[cert_count].data,
149 entry->SignatureData,
150 certs[cert_count].data_len);
161 free_certificates(certs, cert_count);
168 * Extract digests from UEFI "dbx" variable.
169 * UEFI standard specifies three types of digest - sha256, sha386, sha512.
172 efi_get_forbidden_digests(size_t *count)
176 EFI_SIGNATURE_LIST *list;
177 EFI_SIGNATURE_DATA *entry;
178 size_t db_size, header_size, hash_size;
179 int digest_count, entry_count;
187 status = efi_getenv(&ImageSecurityDatabaseGUID, "dbx", database, &db_size);
188 if (status != EFI_BUFFER_TOO_SMALL)
191 database = malloc(db_size);
192 if (database == NULL)
195 status = efi_getenv(&ImageSecurityDatabaseGUID, "dbx", database, &db_size);
196 if (status != EFI_SUCCESS)
200 for (list = (EFI_SIGNATURE_LIST*) database;
201 db_size >= list->SignatureListSize && db_size > 0;
202 db_size -= list->SignatureListSize,
203 list = (EFI_SIGNATURE_LIST*)
204 ((UINT8*)list + list->SignatureListSize)) {
206 /* We are only interested in entries that contain digests. */
207 if (memcmp(&efiCertX509Sha256GUID, &list->SignatureType,
208 sizeof(EFI_GUID)) == 0) {
209 hash_size = br_sha256_SIZE;
210 } else if (memcmp(&efiCertX509Sha384GUID, &list->SignatureType,
211 sizeof(EFI_GUID)) == 0) {
212 hash_size = br_sha384_SIZE;
213 } else if (memcmp(&efiCertX509Sha5122UID, &list->SignatureType,
214 sizeof(EFI_GUID)) == 0) {
215 hash_size = br_sha512_SIZE;
221 * A single entry can have multiple digests
222 * of the same type for some reason.
224 header_size = sizeof(EFI_SIGNATURE_LIST) + list->SignatureHeaderSize;
226 /* Calculate the number of entries basing on structure size */
227 entry_count = list->SignatureListSize - header_size;
228 entry_count /= list->SignatureSize;
229 entry = (EFI_SIGNATURE_DATA*)((UINT8*)list + header_size);
230 while (entry_count-- > 0) {
231 digests = realloc(digests,
232 (digest_count + 1) * sizeof(hash_data));
233 if (digests == NULL) {
238 digests[digest_count].data = malloc(hash_size);
239 if (digests[digest_count].data == NULL)
242 memcpy(digests[digest_count].data,
243 entry->SignatureData,
245 digests[digest_count].hash_size = hash_size;
247 entry = (EFI_SIGNATURE_DATA*)(entry + list->SignatureSize);
253 *count = digest_count;
258 while (digest_count--)
259 xfree(digests[digest_count].data);
266 /* Copy x509 certificates from db */
268 efi_get_trusted_certs(size_t *count)
270 return (efi_get_certs("db", count));
273 /* Copy forbidden certificates from dbx */
275 efi_get_forbidden_certs(size_t *count)
277 return (efi_get_certs("dbx", count));