113ea0450SMarcin Wojtas /*-
213ea0450SMarcin Wojtas * Copyright (c) 2019 Stormshield.
313ea0450SMarcin Wojtas * Copyright (c) 2019 Semihalf.
413ea0450SMarcin Wojtas *
513ea0450SMarcin Wojtas * Redistribution and use in source and binary forms, with or without
613ea0450SMarcin Wojtas * modification, are permitted provided that the following conditions
713ea0450SMarcin Wojtas * are met:
813ea0450SMarcin Wojtas * 1. Redistributions of source code must retain the above copyright
913ea0450SMarcin Wojtas * notice, this list of conditions and the following disclaimer.
1013ea0450SMarcin Wojtas * 2. Redistributions in binary form must reproduce the above copyright
1113ea0450SMarcin Wojtas * notice, this list of conditions and the following disclaimer in the
1213ea0450SMarcin Wojtas * documentation and/or other materials provided with the distribution.
1313ea0450SMarcin Wojtas *
1413ea0450SMarcin Wojtas * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1513ea0450SMarcin Wojtas * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
1613ea0450SMarcin Wojtas * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1713ea0450SMarcin Wojtas * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
1813ea0450SMarcin Wojtas * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
1913ea0450SMarcin Wojtas * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2013ea0450SMarcin Wojtas * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2113ea0450SMarcin Wojtas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
2213ea0450SMarcin Wojtas * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
2313ea0450SMarcin Wojtas * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2413ea0450SMarcin Wojtas * POSSIBILITY OF SUCH DAMAGE.
2513ea0450SMarcin Wojtas */
2613ea0450SMarcin Wojtas
2713ea0450SMarcin Wojtas #include <sys/cdefs.h>
2813ea0450SMarcin Wojtas #include <stand.h>
2913ea0450SMarcin Wojtas #include <string.h>
3013ea0450SMarcin Wojtas
3113ea0450SMarcin Wojtas #include <efi.h>
3213ea0450SMarcin Wojtas #include <efilib.h>
3313ea0450SMarcin Wojtas #include <Guid/ImageAuthentication.h>
3413ea0450SMarcin Wojtas
3513ea0450SMarcin Wojtas #define NEED_BRSSL_H
3613ea0450SMarcin Wojtas #include "../libsecureboot-priv.h"
3713ea0450SMarcin Wojtas #include <brssl.h>
3813ea0450SMarcin Wojtas
3913ea0450SMarcin Wojtas static EFI_GUID ImageSecurityDatabaseGUID = EFI_IMAGE_SECURITY_DATABASE_GUID;
4013ea0450SMarcin Wojtas
4113ea0450SMarcin Wojtas static EFI_GUID efiCertX509GUID = EFI_CERT_X509_GUID;
4213ea0450SMarcin Wojtas static EFI_GUID efiCertX509Sha256GUID = EFI_CERT_X509_SHA256_GUID;
4313ea0450SMarcin Wojtas static EFI_GUID efiCertX509Sha384GUID = EFI_CERT_X509_SHA384_GUID;
4413ea0450SMarcin Wojtas static EFI_GUID efiCertX509Sha5122UID = EFI_CERT_X509_SHA512_GUID;
4513ea0450SMarcin Wojtas
4613ea0450SMarcin Wojtas /*
4713ea0450SMarcin Wojtas * Check if Secure Boot is enabled in firmware.
4813ea0450SMarcin Wojtas * We evaluate two variables - Secure Boot and Setup Mode.
4913ea0450SMarcin Wojtas * Secure Boot is enforced only if the first one equals 1 and the other 0.
5013ea0450SMarcin Wojtas */
5113ea0450SMarcin Wojtas int
efi_secure_boot_enabled(void)5213ea0450SMarcin Wojtas efi_secure_boot_enabled(void)
5313ea0450SMarcin Wojtas {
5413ea0450SMarcin Wojtas UINT8 SecureBoot;
5513ea0450SMarcin Wojtas UINT8 SetupMode;
5613ea0450SMarcin Wojtas size_t length;
5713ea0450SMarcin Wojtas EFI_STATUS status;
5813ea0450SMarcin Wojtas
5913ea0450SMarcin Wojtas length = sizeof(SecureBoot);
6013ea0450SMarcin Wojtas status = efi_global_getenv("SecureBoot", &SecureBoot, &length);
6113ea0450SMarcin Wojtas if (status != EFI_SUCCESS) {
6213ea0450SMarcin Wojtas if (status == EFI_NOT_FOUND)
6313ea0450SMarcin Wojtas return (0);
6413ea0450SMarcin Wojtas
6513ea0450SMarcin Wojtas printf("Failed to read \"SecureBoot\" variable\n");
6613ea0450SMarcin Wojtas return (-efi_status_to_errno(status));
6713ea0450SMarcin Wojtas }
6813ea0450SMarcin Wojtas
6913ea0450SMarcin Wojtas length = sizeof(SetupMode);
7013ea0450SMarcin Wojtas status = efi_global_getenv("SetupMode", &SetupMode, &length);
7113ea0450SMarcin Wojtas if (status != EFI_SUCCESS)
7213ea0450SMarcin Wojtas SetupMode = 0;
7313ea0450SMarcin Wojtas
7413ea0450SMarcin Wojtas printf(" SecureBoot: %d, SetupMode: %d\n", SecureBoot, SetupMode);
7513ea0450SMarcin Wojtas
7613ea0450SMarcin Wojtas return (SecureBoot == 1 && SetupMode == 0);
7713ea0450SMarcin Wojtas }
7813ea0450SMarcin Wojtas
7913ea0450SMarcin Wojtas /*
8013ea0450SMarcin Wojtas * Iterate through UEFI variable and extract X509 certificates from it.
8113ea0450SMarcin Wojtas * The EFI_* structures and related guids are defined in UEFI standard.
8213ea0450SMarcin Wojtas */
8313ea0450SMarcin Wojtas static br_x509_certificate*
efi_get_certs(const char * name,size_t * count)8413ea0450SMarcin Wojtas efi_get_certs(const char *name, size_t *count)
8513ea0450SMarcin Wojtas {
8613ea0450SMarcin Wojtas br_x509_certificate *certs;
8713ea0450SMarcin Wojtas UINT8 *database;
8813ea0450SMarcin Wojtas EFI_SIGNATURE_LIST *list;
8913ea0450SMarcin Wojtas EFI_SIGNATURE_DATA *entry;
9013ea0450SMarcin Wojtas size_t db_size;
9113ea0450SMarcin Wojtas ssize_t cert_count;
9213ea0450SMarcin Wojtas EFI_STATUS status;
9313ea0450SMarcin Wojtas
9413ea0450SMarcin Wojtas database = NULL;
9513ea0450SMarcin Wojtas certs = NULL;
9613ea0450SMarcin Wojtas db_size = 0;
9713ea0450SMarcin Wojtas cert_count = 0;
9813ea0450SMarcin Wojtas
9913ea0450SMarcin Wojtas /*
10013ea0450SMarcin Wojtas * Read variable length and allocate memory for it
10113ea0450SMarcin Wojtas */
10213ea0450SMarcin Wojtas status = efi_getenv(&ImageSecurityDatabaseGUID, name, database, &db_size);
10313ea0450SMarcin Wojtas if (status != EFI_BUFFER_TOO_SMALL)
10413ea0450SMarcin Wojtas return (NULL);
10513ea0450SMarcin Wojtas
10613ea0450SMarcin Wojtas database = malloc(db_size);
10713ea0450SMarcin Wojtas if (database == NULL)
10813ea0450SMarcin Wojtas return (NULL);
10913ea0450SMarcin Wojtas
11013ea0450SMarcin Wojtas status = efi_getenv(&ImageSecurityDatabaseGUID, name, database, &db_size);
11113ea0450SMarcin Wojtas if (status != EFI_SUCCESS)
11213ea0450SMarcin Wojtas goto fail;
11313ea0450SMarcin Wojtas
11413ea0450SMarcin Wojtas for (list = (EFI_SIGNATURE_LIST*) database;
11513ea0450SMarcin Wojtas db_size >= list->SignatureListSize && db_size > 0;
11613ea0450SMarcin Wojtas db_size -= list->SignatureListSize,
11713ea0450SMarcin Wojtas list = (EFI_SIGNATURE_LIST*)
11813ea0450SMarcin Wojtas ((UINT8*)list + list->SignatureListSize)) {
11913ea0450SMarcin Wojtas
12013ea0450SMarcin Wojtas /* We are only interested in entries containing X509 certs. */
12113ea0450SMarcin Wojtas if (memcmp(&efiCertX509GUID,
12213ea0450SMarcin Wojtas &list->SignatureType,
12313ea0450SMarcin Wojtas sizeof(EFI_GUID)) != 0) {
12413ea0450SMarcin Wojtas continue;
12513ea0450SMarcin Wojtas }
12613ea0450SMarcin Wojtas
12713ea0450SMarcin Wojtas entry = (EFI_SIGNATURE_DATA*)
12813ea0450SMarcin Wojtas ((UINT8*)list +
12913ea0450SMarcin Wojtas sizeof(EFI_SIGNATURE_LIST) +
13013ea0450SMarcin Wojtas list->SignatureHeaderSize);
13113ea0450SMarcin Wojtas
13213ea0450SMarcin Wojtas certs = realloc(certs,
13313ea0450SMarcin Wojtas (cert_count + 1) * sizeof(br_x509_certificate));
13413ea0450SMarcin Wojtas if (certs == NULL) {
13513ea0450SMarcin Wojtas cert_count = 0;
13613ea0450SMarcin Wojtas goto fail;
13713ea0450SMarcin Wojtas }
13813ea0450SMarcin Wojtas
13913ea0450SMarcin Wojtas certs[cert_count].data_len = list->SignatureSize - sizeof(EFI_GUID);
14013ea0450SMarcin Wojtas certs[cert_count].data = malloc(certs[cert_count].data_len);
14113ea0450SMarcin Wojtas if (certs[cert_count].data == NULL)
14213ea0450SMarcin Wojtas goto fail;
14313ea0450SMarcin Wojtas
14413ea0450SMarcin Wojtas memcpy(certs[cert_count].data,
14513ea0450SMarcin Wojtas entry->SignatureData,
14613ea0450SMarcin Wojtas certs[cert_count].data_len);
14713ea0450SMarcin Wojtas
14813ea0450SMarcin Wojtas cert_count++;
14913ea0450SMarcin Wojtas }
15013ea0450SMarcin Wojtas
15113ea0450SMarcin Wojtas *count = cert_count;
15213ea0450SMarcin Wojtas
15313ea0450SMarcin Wojtas xfree(database);
15413ea0450SMarcin Wojtas return (certs);
15513ea0450SMarcin Wojtas
15613ea0450SMarcin Wojtas fail:
15713ea0450SMarcin Wojtas free_certificates(certs, cert_count);
15813ea0450SMarcin Wojtas xfree(database);
15913ea0450SMarcin Wojtas return (NULL);
16013ea0450SMarcin Wojtas
16113ea0450SMarcin Wojtas }
16213ea0450SMarcin Wojtas
16313ea0450SMarcin Wojtas /*
16413ea0450SMarcin Wojtas * Extract digests from UEFI "dbx" variable.
16513ea0450SMarcin Wojtas * UEFI standard specifies three types of digest - sha256, sha386, sha512.
16613ea0450SMarcin Wojtas */
16713ea0450SMarcin Wojtas hash_data*
efi_get_forbidden_digests(size_t * count)16813ea0450SMarcin Wojtas efi_get_forbidden_digests(size_t *count)
16913ea0450SMarcin Wojtas {
17013ea0450SMarcin Wojtas UINT8 *database;
17113ea0450SMarcin Wojtas hash_data *digests;
17213ea0450SMarcin Wojtas EFI_SIGNATURE_LIST *list;
17313ea0450SMarcin Wojtas EFI_SIGNATURE_DATA *entry;
17413ea0450SMarcin Wojtas size_t db_size, header_size, hash_size;
17513ea0450SMarcin Wojtas int digest_count, entry_count;
17613ea0450SMarcin Wojtas EFI_STATUS status;
17713ea0450SMarcin Wojtas
17813ea0450SMarcin Wojtas db_size = 0;
17913ea0450SMarcin Wojtas digest_count = 0;
18013ea0450SMarcin Wojtas database = NULL;
18113ea0450SMarcin Wojtas digests = NULL;
18213ea0450SMarcin Wojtas
18313ea0450SMarcin Wojtas status = efi_getenv(&ImageSecurityDatabaseGUID, "dbx", database, &db_size);
18413ea0450SMarcin Wojtas if (status != EFI_BUFFER_TOO_SMALL)
18513ea0450SMarcin Wojtas return (NULL);
18613ea0450SMarcin Wojtas
18713ea0450SMarcin Wojtas database = malloc(db_size);
18813ea0450SMarcin Wojtas if (database == NULL)
18913ea0450SMarcin Wojtas return (NULL);
19013ea0450SMarcin Wojtas
19113ea0450SMarcin Wojtas status = efi_getenv(&ImageSecurityDatabaseGUID, "dbx", database, &db_size);
19213ea0450SMarcin Wojtas if (status != EFI_SUCCESS)
19313ea0450SMarcin Wojtas goto fail;
19413ea0450SMarcin Wojtas
19513ea0450SMarcin Wojtas
19613ea0450SMarcin Wojtas for (list = (EFI_SIGNATURE_LIST*) database;
19713ea0450SMarcin Wojtas db_size >= list->SignatureListSize && db_size > 0;
19813ea0450SMarcin Wojtas db_size -= list->SignatureListSize,
19913ea0450SMarcin Wojtas list = (EFI_SIGNATURE_LIST*)
20013ea0450SMarcin Wojtas ((UINT8*)list + list->SignatureListSize)) {
20113ea0450SMarcin Wojtas
20213ea0450SMarcin Wojtas /* We are only interested in entries that contain digests. */
20313ea0450SMarcin Wojtas if (memcmp(&efiCertX509Sha256GUID, &list->SignatureType,
20413ea0450SMarcin Wojtas sizeof(EFI_GUID)) == 0) {
20513ea0450SMarcin Wojtas hash_size = br_sha256_SIZE;
20613ea0450SMarcin Wojtas } else if (memcmp(&efiCertX509Sha384GUID, &list->SignatureType,
20713ea0450SMarcin Wojtas sizeof(EFI_GUID)) == 0) {
20813ea0450SMarcin Wojtas hash_size = br_sha384_SIZE;
20913ea0450SMarcin Wojtas } else if (memcmp(&efiCertX509Sha5122UID, &list->SignatureType,
21013ea0450SMarcin Wojtas sizeof(EFI_GUID)) == 0) {
21113ea0450SMarcin Wojtas hash_size = br_sha512_SIZE;
21213ea0450SMarcin Wojtas } else {
21313ea0450SMarcin Wojtas continue;
21413ea0450SMarcin Wojtas }
21513ea0450SMarcin Wojtas
21613ea0450SMarcin Wojtas /*
21713ea0450SMarcin Wojtas * A single entry can have multiple digests
21813ea0450SMarcin Wojtas * of the same type for some reason.
21913ea0450SMarcin Wojtas */
22013ea0450SMarcin Wojtas header_size = sizeof(EFI_SIGNATURE_LIST) + list->SignatureHeaderSize;
22113ea0450SMarcin Wojtas
22213ea0450SMarcin Wojtas /* Calculate the number of entries basing on structure size */
22313ea0450SMarcin Wojtas entry_count = list->SignatureListSize - header_size;
22413ea0450SMarcin Wojtas entry_count /= list->SignatureSize;
22513ea0450SMarcin Wojtas entry = (EFI_SIGNATURE_DATA*)((UINT8*)list + header_size);
22613ea0450SMarcin Wojtas while (entry_count-- > 0) {
22713ea0450SMarcin Wojtas digests = realloc(digests,
22813ea0450SMarcin Wojtas (digest_count + 1) * sizeof(hash_data));
22913ea0450SMarcin Wojtas if (digests == NULL) {
23013ea0450SMarcin Wojtas digest_count = 0;
23113ea0450SMarcin Wojtas goto fail;
23213ea0450SMarcin Wojtas }
23313ea0450SMarcin Wojtas
23413ea0450SMarcin Wojtas digests[digest_count].data = malloc(hash_size);
23513ea0450SMarcin Wojtas if (digests[digest_count].data == NULL)
23613ea0450SMarcin Wojtas goto fail;
23713ea0450SMarcin Wojtas
23813ea0450SMarcin Wojtas memcpy(digests[digest_count].data,
23913ea0450SMarcin Wojtas entry->SignatureData,
24013ea0450SMarcin Wojtas hash_size);
24113ea0450SMarcin Wojtas digests[digest_count].hash_size = hash_size;
24213ea0450SMarcin Wojtas
24313ea0450SMarcin Wojtas entry = (EFI_SIGNATURE_DATA*)(entry + list->SignatureSize);
24413ea0450SMarcin Wojtas digest_count++;
24513ea0450SMarcin Wojtas }
24613ea0450SMarcin Wojtas }
24713ea0450SMarcin Wojtas xfree(database);
24813ea0450SMarcin Wojtas if (count != NULL)
24913ea0450SMarcin Wojtas *count = digest_count;
25013ea0450SMarcin Wojtas
25113ea0450SMarcin Wojtas return (digests);
25213ea0450SMarcin Wojtas
25313ea0450SMarcin Wojtas fail:
25413ea0450SMarcin Wojtas while (digest_count--)
25513ea0450SMarcin Wojtas xfree(digests[digest_count].data);
25613ea0450SMarcin Wojtas
25713ea0450SMarcin Wojtas xfree(database);
25813ea0450SMarcin Wojtas xfree(digests);
25913ea0450SMarcin Wojtas return (NULL);
26013ea0450SMarcin Wojtas }
26113ea0450SMarcin Wojtas
26213ea0450SMarcin Wojtas /* Copy x509 certificates from db */
26313ea0450SMarcin Wojtas br_x509_certificate*
efi_get_trusted_certs(size_t * count)26413ea0450SMarcin Wojtas efi_get_trusted_certs(size_t *count)
26513ea0450SMarcin Wojtas {
26613ea0450SMarcin Wojtas return (efi_get_certs("db", count));
26713ea0450SMarcin Wojtas }
26813ea0450SMarcin Wojtas
26913ea0450SMarcin Wojtas /* Copy forbidden certificates from dbx */
27013ea0450SMarcin Wojtas br_x509_certificate*
efi_get_forbidden_certs(size_t * count)27113ea0450SMarcin Wojtas efi_get_forbidden_certs(size_t *count)
27213ea0450SMarcin Wojtas {
27313ea0450SMarcin Wojtas return (efi_get_certs("dbx", count));
27413ea0450SMarcin Wojtas }
275