diff --git a/.gitattributes b/.gitattributes index 812f849..bbe7c23 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,3 +1,4 @@ -*.sh eol=lf -*.patch binary -Makefile eol=lf +*.patch binary +*.sh eol=lf +Makefile eol=lf +sbat_level.txt eol=lf diff --git a/sbat_level.txt b/sbat_level.txt new file mode 100644 index 0000000..2b80ab8 --- /dev/null +++ b/sbat_level.txt @@ -0,0 +1,4 @@ +sbat,1,2024010900 +shim,4 +grub,3 +grub.debian,4 diff --git a/src/data.c b/src/data.c index 90294a0..eb17e31 100644 --- a/src/data.c +++ b/src/data.c @@ -670,6 +670,15 @@ unsigned char db_ms1_cer[] = { }; unsigned int db_ms1_cer_len = 1499; +// From https://github.com/pbatard/Mosby/raw/main/sbat_level.txt +unsigned char sbat_level_txt[] = { + 0x73, 0x62, 0x61, 0x74, 0x2c, 0x31, 0x2c, 0x32, 0x30, 0x32, 0x34, 0x30, + 0x31, 0x30, 0x39, 0x30, 0x30, 0x0a, 0x73, 0x68, 0x69, 0x6d, 0x2c, 0x34, + 0x0a, 0x67, 0x72, 0x75, 0x62, 0x2c, 0x33, 0x0a, 0x67, 0x72, 0x75, 0x62, + 0x2e, 0x64, 0x65, 0x62, 0x69, 0x61, 0x6e, 0x2c, 0x34, 0x0a +}; +unsigned int sbat_level_txt_len = 46; + // From https://uefi.org/sites/default/files/resources/arm_DBXUpdate.bin unsigned char dbx_arm_bin[] = { 0xda, 0x07, 0x03, 0x06, 0x13, 0x11, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -4328,83 +4337,102 @@ EFI_STATUS InitializeList( IN OUT MOSBY_LIST *List ) { - if (MOSBY_MAX_LIST_SIZE < 10) + if (MOSBY_MAX_LIST_SIZE < 11) return EFI_INVALID_PARAMETER; ZeroMem(List, sizeof(MOSBY_LIST)); - List->Entry[List->Size].Description = "Microsoft Corporation KEK CA 2011"; List->Entry[List->Size].Type = KEK; + List->Entry[List->Size].Attrs = UEFI_VAR_NV_BS_RT_TIMEAUTH; List->Entry[List->Size].Path = L"kek_ms1.cer"; List->Entry[List->Size].Url = "https://go.microsoft.com/fwlink/?LinkId=321185"; + List->Entry[List->Size].Description = "Microsoft Corporation KEK CA 2011"; List->Entry[List->Size].Buffer.Data = kek_ms1_cer; List->Entry[List->Size].Buffer.Size = kek_ms1_cer_len; List->Size++; - List->Entry[List->Size].Description = "Microsoft Corporation KEK 2K CA 2023"; List->Entry[List->Size].Type = KEK; + List->Entry[List->Size].Attrs = UEFI_VAR_NV_BS_RT_TIMEAUTH; List->Entry[List->Size].Path = L"kek_ms2.cer"; List->Entry[List->Size].Url = "https://go.microsoft.com/fwlink/?linkid=2239775"; + List->Entry[List->Size].Description = "Microsoft Corporation KEK 2K CA 2023"; List->Entry[List->Size].Buffer.Data = kek_ms2_cer; List->Entry[List->Size].Buffer.Size = kek_ms2_cer_len; List->Size++; - List->Entry[List->Size].Description = "Windows UEFI CA 2023"; List->Entry[List->Size].Type = DB; + List->Entry[List->Size].Attrs = UEFI_VAR_NV_BS_RT_TIMEAUTH; List->Entry[List->Size].Path = L"db_ms3.cer"; List->Entry[List->Size].Url = "https://go.microsoft.com/fwlink/?linkid=2239776"; + List->Entry[List->Size].Description = "Windows UEFI CA 2023"; List->Entry[List->Size].Buffer.Data = db_ms3_cer; List->Entry[List->Size].Buffer.Size = db_ms3_cer_len; List->Size++; - List->Entry[List->Size].Description = "Microsoft Corporation UEFI CA 2011"; List->Entry[List->Size].Type = DB; + List->Entry[List->Size].Attrs = UEFI_VAR_NV_BS_RT_TIMEAUTH; List->Entry[List->Size].Path = L"db_ms2.cer"; List->Entry[List->Size].Url = "https://go.microsoft.com/fwlink/?linkid=321194"; + List->Entry[List->Size].Description = "Microsoft Corporation UEFI CA 2011"; List->Entry[List->Size].Buffer.Data = db_ms2_cer; List->Entry[List->Size].Buffer.Size = db_ms2_cer_len; List->Size++; - List->Entry[List->Size].Description = "Microsoft Windows Production PCA 2011"; List->Entry[List->Size].Type = DB; + List->Entry[List->Size].Attrs = UEFI_VAR_NV_BS_RT_TIMEAUTH; List->Entry[List->Size].Path = L"db_ms1.cer"; List->Entry[List->Size].Url = "https://go.microsoft.com/fwlink/?linkid=321192"; + List->Entry[List->Size].Description = "Microsoft Windows Production PCA 2011"; List->Entry[List->Size].Buffer.Data = db_ms1_cer; List->Entry[List->Size].Buffer.Size = db_ms1_cer_len; List->Size++; + List->Entry[List->Size].Type = SBAT; + List->Entry[List->Size].Flags = USE_BUFFER; + List->Entry[List->Size].Attrs = UEFI_VAR_NV_BS; + List->Entry[List->Size].Path = L"sbat_level.txt"; + List->Entry[List->Size].Url = "https://github.com/pbatard/Mosby/raw/main/sbat_level.txt"; + List->Entry[List->Size].Description = "SbatLevel.txt [2024.01.09]"; + List->Entry[List->Size].Buffer.Data = sbat_level_txt; + List->Entry[List->Size].Buffer.Size = sbat_level_txt_len; + List->Size++; #if defined (_M_ARM) || defined(__arm__) - List->Entry[List->Size].Description = "DBX for ARM (32 bit) [2023.05.09]"; List->Entry[List->Size].Type = DBX; + List->Entry[List->Size].Attrs = UEFI_VAR_NV_BS_RT_TIMEAUTH; List->Entry[List->Size].Path = L"dbx_arm.bin"; List->Entry[List->Size].Url = "https://uefi.org/sites/default/files/resources/arm_DBXUpdate.bin"; + List->Entry[List->Size].Description = "DBX for ARM (32 bit) [2023.05.09]"; List->Entry[List->Size].Buffer.Data = dbx_arm_bin; List->Entry[List->Size].Buffer.Size = dbx_arm_bin_len; List->Size++; #endif - List->Entry[List->Size].Description = "Microsoft UEFI CA 2023"; List->Entry[List->Size].Type = DB; + List->Entry[List->Size].Attrs = UEFI_VAR_NV_BS_RT_TIMEAUTH; List->Entry[List->Size].Path = L"db_ms4.cer"; List->Entry[List->Size].Url = "https://go.microsoft.com/fwlink/?linkid=2239872"; + List->Entry[List->Size].Description = "Microsoft UEFI CA 2023"; List->Entry[List->Size].Buffer.Data = db_ms4_cer; List->Entry[List->Size].Buffer.Size = db_ms4_cer_len; List->Size++; #if defined (_M_ARM64) || defined(__aarch64__) - List->Entry[List->Size].Description = "DBX for ARM (64 bit) [2023.05.09]"; List->Entry[List->Size].Type = DBX; + List->Entry[List->Size].Attrs = UEFI_VAR_NV_BS_RT_TIMEAUTH; List->Entry[List->Size].Path = L"dbx_aa64.bin"; List->Entry[List->Size].Url = "https://uefi.org/sites/default/files/resources/arm64_DBXUpdate.bin"; + List->Entry[List->Size].Description = "DBX for ARM (64 bit) [2023.05.09]"; List->Entry[List->Size].Buffer.Data = dbx_aa64_bin; List->Entry[List->Size].Buffer.Size = dbx_aa64_bin_len; List->Size++; #endif #if defined(_M_X64) || defined(__x86_64__) - List->Entry[List->Size].Description = "DBX for x86 (64 bit) [2023.05.09]"; List->Entry[List->Size].Type = DBX; + List->Entry[List->Size].Attrs = UEFI_VAR_NV_BS_RT_TIMEAUTH; List->Entry[List->Size].Path = L"dbx_x64.bin"; List->Entry[List->Size].Url = "https://uefi.org/sites/default/files/resources/x64_DBXUpdate.bin"; + List->Entry[List->Size].Description = "DBX for x86 (64 bit) [2023.05.09]"; List->Entry[List->Size].Buffer.Data = dbx_x64_bin; List->Entry[List->Size].Buffer.Size = dbx_x64_bin_len; List->Size++; #endif #if defined(_M_IX86) || defined(__i386__) - List->Entry[List->Size].Description = "DBX for x86 (32 bit) [2023.05.09]"; List->Entry[List->Size].Type = DBX; + List->Entry[List->Size].Attrs = UEFI_VAR_NV_BS_RT_TIMEAUTH; List->Entry[List->Size].Path = L"dbx_ia32.bin"; List->Entry[List->Size].Url = "https://uefi.org/sites/default/files/resources/x86_DBXUpdate.bin"; + List->Entry[List->Size].Description = "DBX for x86 (32 bit) [2023.05.09]"; List->Entry[List->Size].Buffer.Data = dbx_ia32_bin; List->Entry[List->Size].Buffer.Size = dbx_ia32_bin_len; List->Size++; diff --git a/src/file.c b/src/file.c index cd6b8ba..eabae51 100644 --- a/src/file.c +++ b/src/file.c @@ -252,8 +252,8 @@ EFI_STATUS SimpleFileReadAll( } // Might use memory mapped, so align up to nearest page. - // Also + 1 so the data is always NUL terminated. - *Buffer = AllocateZeroPool(ALIGN_VALUE(*Size + 1, 4096)); + // Also + 2 so the data is always NUL terminated. + *Buffer = AllocateZeroPool(ALIGN_VALUE(*Size + 2, 4096)); if (*Buffer == NULL) { Status = EFI_OUT_OF_RESOURCES; ReportErrorAndExit(L"Failed to allocate buffer of size %d\n", *Size); diff --git a/src/gen_data.sh b/src/gen_data.sh index 2b61811..f02d82e 100755 --- a/src/gen_data.sh +++ b/src/gen_data.sh @@ -1,5 +1,5 @@ #!/bin/env bash -# This script generates the C source for the data we want to embed in Mosby. +# This script generates the C source for the data we embed in Mosby. # The binaries we want to embedd and their URLs declare -A source=( @@ -13,6 +13,9 @@ declare -A source=( [dbx_ia32.bin]='https://uefi.org/sites/default/files/resources/x86_DBXUpdate.bin' [dbx_aa64.bin]='https://uefi.org/sites/default/files/resources/arm64_DBXUpdate.bin' [dbx_arm.bin]='https://uefi.org/sites/default/files/resources/arm_DBXUpdate.bin' + # Shim does not provide an SBatLevel.txt we can download, so we use our own: + # https://github.com/rhboot/shim/issues/685 + [sbat_level.txt]='https://github.com/pbatard/Mosby/raw/main/sbat_level.txt' ) # From https://uefi.org/revocationlistfile. @@ -70,13 +73,26 @@ cat << EOF EOF for file in "${!source[@]}"; do - curl -s -L ${source[${file}]} -o ${file} + # '-o' tries to use an override from the current repo + if [[ "$1" == "-o" && -f ../${file} ]]; then + cp ../${file} . + else + curl -s -L ${source[${file}]} -o ${file} + fi echo "// From ${source[${file}]}" type=${file%%_*} if [ "$type" = "dbx" ]; then arch=${file%\.*} arch=${arch##*_} description[${file}]="DBX for ${archname[$arch]} [${archdate[$arch]}]" + elif [ "$type" = "sbat" ]; then + while IFS=, read -r c1 c2 c3; do + if [ "$c1" = "sbat" ]; then + date="[${c3:0:4}.${c3:4:2}.${c3:6:2}]" + break + fi + done < ${file} + description[${file}]="SbatLevel.txt $date" else description[${file}]="$(openssl x509 -noout -subject -in ${file} | sed -n '/^subject/s/^.*CN = //p')" fi @@ -100,10 +116,18 @@ for file in "${!source[@]}"; do if [ "$type" = "DBX" ]; then echo "${archguard[$arch]}" fi - echo " List->Entry[List->Size].Description = \"${description[${file}]}\";" echo " List->Entry[List->Size].Type = ${type};" + if [[ "$type" = "SBAT" ]]; then + echo " List->Entry[List->Size].Flags = USE_BUFFER;" + fi + if [[ "$type" = "SBAT" || "$type" = "MOK" ]]; then + echo " List->Entry[List->Size].Attrs = UEFI_VAR_NV_BS;" + else + echo " List->Entry[List->Size].Attrs = UEFI_VAR_NV_BS_RT_TIMEAUTH;" + fi echo " List->Entry[List->Size].Path = L\"${file}\";" echo " List->Entry[List->Size].Url = \"${source[${file}]}\";" + echo " List->Entry[List->Size].Description = \"${description[${file}]}\";" echo " List->Entry[List->Size].Buffer.Data = ${data};" echo " List->Entry[List->Size].Buffer.Size = ${data}_len;" echo " List->Size++;" diff --git a/src/mosby.c b/src/mosby.c index 209c039..690c90b 100644 --- a/src/mosby.c +++ b/src/mosby.c @@ -42,43 +42,98 @@ STATIC struct { EFI_GUID *VariableGuid; } KeyInfo[MAX_TYPES] = { [PK] = { - .DisplayName = "PK: ", + .DisplayName = "PK: ", .OptionName = L"-pk", .VariableName = EFI_PLATFORM_KEY_NAME, .VariableGuid = &gEfiGlobalVariableGuid, }, [KEK] = { - .DisplayName = "KEK:", + .DisplayName = "KEK: ", .OptionName = L"-kek", .VariableName = EFI_KEY_EXCHANGE_KEY_NAME, .VariableGuid = &gEfiGlobalVariableGuid, }, [DB] = { - .DisplayName = "DB: ", + .DisplayName = "DB: ", .OptionName = L"-db", .VariableName = EFI_IMAGE_SECURITY_DATABASE, .VariableGuid = &gEfiImageSecurityDatabaseGuid, }, [DBX] = { - .DisplayName = "DBX:", + .DisplayName = "DBX: ", .OptionName = L"-dbx", .VariableName = EFI_IMAGE_SECURITY_DATABASE1, .VariableGuid = &gEfiImageSecurityDatabaseGuid, }, [DBT] = { - .DisplayName = "DBT:", + .DisplayName = "DBT: ", .OptionName = L"-dbt", .VariableName = EFI_IMAGE_SECURITY_DATABASE2, .VariableGuid = &gEfiImageSecurityDatabaseGuid, }, [MOK] = { - .DisplayName = "MOK:", + .DisplayName = "MOK: ", .OptionName = L"-mok", .VariableName = L"MokList", .VariableGuid = &gEfiShimLockGuid, + }, + [SBAT] = { + .DisplayName = "SBAT:", + .OptionName = L"-sbat", + .VariableName = L"SbatLevel", + .VariableGuid = &gEfiShimLockGuid, } }; +STATIC EFI_STATUS ReadVariable( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN OUT UINTN *DataSize, + OUT VOID **Data +) +{ + EFI_STATUS Status; + + *DataSize = 0; + *Data = NULL; + Status = gRT->GetVariable(VariableName, VendorGuid, NULL, DataSize, NULL); + if (EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL) + return Status; + // +2 to ensure that we have NUL terminators always + *Data = AllocateZeroPool(*DataSize + 2); + if (*Data == NULL) + return EFI_OUT_OF_RESOURCES; + + return gRT->GetVariable(VariableName, VendorGuid, NULL, DataSize, *Data); +} + +STATIC UINT32 GetSBatVersion( + IN CHAR8 *SBat, + IN UINTN SBatSize +) +{ + UINT32 i, v, m; + + if (SBatSize < 17) + goto error; + if (SBat[0] != 's' || SBat[1] != 'b' || SBat[2] != 'a' || SBat[3] != 't' || SBat[4] != ',') + goto error; + for (i = 5; i < SBatSize && SBat[i] != ',' && SBat[i] != '\n'; i++); + if (SBat[i++] != ',' || SBat[i] != '2') + goto error; + v = 0; + for (m = 1000000000; m > 0; m /= 10, i++) { + if (SBat[i] < '0' || SBat[i] > '9') + goto error; + v += (SBat[i] - '0') * m; + } + return v; + +error: + RecallPrint(L"ERROR: Unexpected SBAT data\n"); + return 0; +} + /* * Application entry-point */ @@ -87,22 +142,17 @@ EFI_STATUS EFIAPI efi_main( IN EFI_SYSTEM_TABLE* SystemTable ) { - // TODO: MOK may need different options - CONST UINT32 Attributes = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS; BOOLEAN TestMode = FALSE, GenDBCred = FALSE, Append; EFI_STATUS Status; EFI_TIME Time; - UINTN i, NumPKs; - INTN Argc, Type, Sel; + UINTN i, NumPKs, Size; + INTN Argc, Type, Sel, LastSBat; MOSBY_CRED Cred; - CHAR8 DbSubject[80], PkSubject[80]; + CHAR8 DbSubject[80], PkSubject[80], *SBat, *SBatLine; CHAR16 **Argv = NULL, **ArgvCopy, MosbyKeyPath[MAX_PATH]; MOSBY_LIST List; - RecallPrint(L"Mosby %s %a\n", ARCH_EXT, VERSION_STRING); gBaseImageHandle = BaseImageHandle; - gRT->GetTime(&Time, NULL); /* Initialize the base entry list */ Status = InitializeList(&List); @@ -123,18 +173,38 @@ EFI_STATUS EFIAPI efi_main( ArgvCopy += 1; Argc -= 1; } else if (StrCmp(ArgvCopy[1], L"-h") == 0) { - Print(L"Usage: Mosby [-i] [-h] [-s] [-v] [-{var} ] [-{var} ] [...]\n"); - Print(L" Supported {var} values: pk, kek, db, dbx, dbt, mok\n"); + Print(L"Usage: Mosby [-i] [-h] [-s] [-v] [-var ] [-var ] [...]\n"); + Print(L" Supported var values: pk, kek, db, dbx, dbt, mok, sbat\n"); goto exit; } else if (StrCmp(ArgvCopy[1], L"-v") == 0) { + Print(L"Mosby %s %a\n", ARCH_EXT, VERSION_STRING); goto exit; } else if (StrCmp(ArgvCopy[1], L"-i") == 0) { + Print(L"Embedded data:\n"); for (i = 0; i < List.Size; i++) { if (List.Entry[i].Description != NULL) { - Print(L"o %a %a\n From %a\n", KeyInfo[List.Entry[i].Type].DisplayName, + Print(L"o %a %a\n From %a\n", KeyInfo[List.Entry[i].Type].DisplayName, List.Entry[i].Description, List.Entry[i].Url); - Print(L" %a\n", Sha256ToString(List.Entry[i].Buffer.Data, List.Entry[i].Buffer.Size)); + Print(L" %a\n", Sha256ToString(List.Entry[i].Buffer.Data, List.Entry[i].Buffer.Size)); + } + } + if (ReadVariable(L"SbatLevel", &gEfiShimLockGuid, &Size, (VOID**)&SBat) == EFI_SUCCESS) { + Print(L"\nCurrent system SBAT:\n"); + for (SBatLine = SBat; SBatLine[0] != '\0'; ) { + for (i = 0; ; i++) { + if (SBatLine[i] == '\n') { + SBatLine[i] = '\0'; + Print(L"%a\n", SBatLine); + SBatLine = &SBatLine[i + 1]; + break; + } else if (SBatLine[i] == '\0') { + Print(L"%a\n", SBatLine); + SBatLine = &SBatLine[i]; + break; + } + } } + SafeFree(SBat); } goto exit; } else { @@ -254,9 +324,42 @@ EFI_STATUS EFIAPI efi_main( if (EFI_ERROR(Status)) goto exit; } - Status = PopulateAuthVar(&List.Entry[i]); - if (EFI_ERROR(Status)) - ReportErrorAndExit(L"Failed to create variable - Aborting\n"); + if (List.Entry[i].Type == SBAT) { + List.Entry[i].Flags = USE_BUFFER; + List.Entry[i].Attrs = UEFI_VAR_NV_BS; + } else { + Status = PopulateAuthVar(&List.Entry[i]); + if (EFI_ERROR(Status)) + ReportErrorAndExit(L"Failed to create variable - Aborting\n"); + } + } + + /* Find out if we need to update the SBAT */ + LastSBat = -1; + for (i = 0; i < List.Size; i++) { + if (List.Entry[i].Type != SBAT) + continue; + // Override internal SBAT if one was provided by the user + if (LastSBat >= 0) + List.Entry[LastSBat].Flags |= NO_INSTALL; + LastSBat = i; + } + if (LastSBat >= 0) { + UINT32 SystemSBatVer = 0, InstallSBatVer; + InstallSBatVer = GetSBatVersion((CHAR8*)List.Entry[LastSBat].Buffer.Data, List.Entry[LastSBat].Buffer.Size); + if (InstallSBatVer == 0) + goto exit; + Status = ReadVariable(L"SbatLevel", &gEfiShimLockGuid, &Size, (VOID**)&SBat); + if (Status == EFI_SUCCESS) + SystemSBatVer = GetSBatVersion(SBat, Size); + if (TestMode) + Print(L"Provided SBAT: %d, System SBAT: %d\n", InstallSBatVer, SystemSBatVer); + if (InstallSBatVer <= SystemSBatVer) { + // TODO: Allow override + RecallPrint(L"Not installing SBAT since this system's SBAT is either the same or newer\n"); + List.Entry[LastSBat].Flags |= NO_INSTALL; + } + SafeFree(SBat); } /* Generate DB credentials if requested */ @@ -268,6 +371,9 @@ EFI_STATUS EFIAPI efi_main( i = List.Size; RecallPrint(L"Generating Secure Boot signing credentials...\n"); List.Entry[i].Type = DB; + Status = gRT->GetTime(&Time, NULL); + if (EFI_ERROR(Status)) + ReportErrorAndExit(L"Failed to get time - Aborting\n"); AsciiSPrint(DbSubject, sizeof(DbSubject), "%a [%04d.%02d.%02d]", MOSBY_CRED_NAME, Time.Year, Time.Month, Time.Day); List.Entry[i].Description = DbSubject; @@ -279,6 +385,7 @@ EFI_STATUS EFIAPI efi_main( FreeCredentials(&Cred); goto exit; } + List.Entry[i].Attrs = UEFI_VAR_NV_BS_RT_TIMEAUTH; Status = SaveCredentials(WIDEN(MOSBY_CRED_NAME), &Cred); if (EFI_ERROR(Status)) goto exit; @@ -288,9 +395,13 @@ EFI_STATUS EFIAPI efi_main( } /* Generate a keyless PK cert if none was specified */ - for (i = 0, NumPKs = 0; i < List.Size; i++) - if (List.Entry[i].Type == PK) + for (i = 0, NumPKs = 0; i < List.Size; i++) { + if (List.Entry[i].Type == PK) { NumPKs++; + if (NumPKs > 1) + List.Entry[i].Flags |= NO_INSTALL; + } + } if (NumPKs >= 2) RecallPrint(L"WARNING: More than one PK was specified. Only the first will be used."); if (NumPKs == 0) { @@ -300,6 +411,11 @@ EFI_STATUS EFIAPI efi_main( } RecallPrint(L"Generating PK certificate...\n"); List.Entry[i].Type = PK; + if (!GenDBCred) { + Status = gRT->GetTime(&Time, NULL); + if (EFI_ERROR(Status)) + ReportErrorAndExit(L"Failed to get time - Aborting\n"); + } AsciiSPrint(PkSubject, sizeof(PkSubject), "Mosby Generated PK [%04d.%02d.%02d]", Time.Year, Time.Month, Time.Day); List.Entry[i].Description = PkSubject; @@ -312,8 +428,9 @@ EFI_STATUS EFIAPI efi_main( goto exit; } // PK must be signed + List.Entry[i].Attrs = UEFI_VAR_NV_BS_RT_TIMEAUTH; Status = SignToAuthVar(KeyInfo[PK].VariableName, KeyInfo[PK].VariableGuid, - Attributes, &List.Entry[i].Variable, &Cred); + List.Entry[i].Attrs, &List.Entry[i].Variable, &Cred); FreeCredentials(&Cred); if (EFI_ERROR(Status)) { SafeFree(List.Entry[i].Variable.Data); @@ -322,27 +439,25 @@ EFI_STATUS EFIAPI efi_main( List.Size++; } - /* Install the variables, making sure that we finish with the PK. */ - // Since We have a DeleteSecureBootVariables(), we might as well call it. + /* EDK2 provides a DeleteSecureBootVariables(), so we might as well call it. */ DeleteSecureBootVariables(); + + /* Install the variables, making sure that we finish with the PK. */ Status = EFI_NOT_FOUND; for (Type = MAX_TYPES - 1; Type >= 0; Type--) { Append = FALSE; for (i = 0; i < List.Size; i++) { - if (List.Entry[i].Type != Type) + if (List.Entry[i].Type != Type || List.Entry[i].Flags & NO_INSTALL) continue; if (List.Entry[i].Description != NULL) RecallPrint(L"Installing %a '%a'\n", KeyInfo[Type].DisplayName, List.Entry[i].Description); else RecallPrint(L"Installing %a From '%s'\n", KeyInfo[Type].DisplayName, List.Entry[i].Path); - Status = gRT->SetVariable(KeyInfo[Type].VariableName, KeyInfo[Type].VariableGuid, - Attributes | (Append ? EFI_VARIABLE_APPEND_WRITE : 0), - List.Entry[i].Variable.Size, List.Entry[i].Variable.Data); + Status = gRT->SetVariable(KeyInfo[Type].VariableName, KeyInfo[Type].VariableGuid, List.Entry[i].Attrs, + (List.Entry[i].Flags & USE_BUFFER) ? List.Entry[i].Buffer.Size : List.Entry[i].Variable.Size, + (List.Entry[i].Flags & USE_BUFFER) ? (VOID*)List.Entry[i].Buffer.Data : (VOID*)List.Entry[i].Variable.Data); if (EFI_ERROR(Status)) ReportErrorAndExit(L"Failed to set Secure Boot variable: %r\n", Status); - // Make sure we only ever process one PK - if (List.Entry[i].Type == PK) - break; Append = TRUE; } } diff --git a/src/mosby.h b/src/mosby.h index 6822faa..35bc0cc 100644 --- a/src/mosby.h +++ b/src/mosby.h @@ -72,6 +72,15 @@ /* FreePool() replacement, that NULLs the freed pointer. */ #define SafeFree(p) do { FreePool(p); p = NULL; } while(0) +/* Variable attributes */ +#define UEFI_VAR_NV_BS (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS) +#define UEFI_VAR_NV_BS_RT (UEFI_VAR_NV_BS | EFI_VARIABLE_RUNTIME_ACCESS) +#define UEFI_VAR_NV_BS_RT_TIMEAUTH (UEFI_VAR_NV_BS_RT | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) + +/* Flags */ +#define USE_BUFFER 1 +#define NO_INSTALL 2 + /* Global Image Handle for the current executable */ extern EFI_HANDLE gBaseImageHandle; @@ -83,6 +92,7 @@ enum { DBX, DBT, MOK, + SBAT, MAX_TYPES }; @@ -101,6 +111,8 @@ typedef struct { /* Mosby installable entry */ typedef struct { UINT8 Type; + BOOLEAN Flags; + UINT32 Attrs; CHAR16 *Path; CHAR8 *Url; CHAR8 *Description; diff --git a/src/pki.c b/src/pki.c index b4fa036..0034230 100644 --- a/src/pki.c +++ b/src/pki.c @@ -427,6 +427,9 @@ EFI_STATUS PopulateAuthVar( if (Entry->Buffer.Size < sizeof(EFI_SIGNATURE_LIST)) ReportErrorAndExit(L"'%s' is too small to be a valid certificate or signature list\n", Entry->Path); + // Set default attributes for authenticated variable + Entry->Attrs = Entry->Type == MOK ? UEFI_VAR_NV_BS : UEFI_VAR_NV_BS_RT_TIMEAUTH; + // Check for signed ESL (PKCS#7 only) SignedEsl = (EFI_VARIABLE_AUTHENTICATION_2*)Entry->Buffer.Data; if (Entry->Buffer.Size > sizeof(EFI_VARIABLE_AUTHENTICATION_2) && @@ -483,6 +486,7 @@ EFI_STATUS PopulateAuthVar( exit: BIO_free(bio); if (EFI_ERROR(Status)) { + Entry->Attrs = 0; Entry->Variable.Size = 0; SafeFree(Entry->Variable.Data); }