diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ae7693a2..93ccd146 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -44,6 +44,15 @@ jobs: - name: Clean limine-version run: rm build/bin/limine-version + - name: Clean limine-enroll-config + run: rm build/bin/limine-enroll-config + + - name: Build limine-enroll-config-win32 + run: make -C build/bin CC="i686-w64-mingw32-gcc" CFLAGS="-O2 -pipe" limine-enroll-config + + - name: Strip limine-enroll-config-win32 + run: i686-w64-mingw32-strip build/bin/limine-enroll-config.exe + - name: Clean limine-deploy run: rm build/bin/limine-deploy diff --git a/GNUmakefile.in b/GNUmakefile.in index 830f18b7..7e218548 100644 --- a/GNUmakefile.in +++ b/GNUmakefile.in @@ -83,7 +83,7 @@ override LIMINE_VERSION := @PACKAGE_VERSION@ override STAGE1_FILES := $(shell find '$(call SHESCAPE,$(SRCDIR))/stage1' -type f -name '*.asm') .PHONY: all -all: limine-version $(BUILD_UEFI_X86_64) $(BUILD_UEFI_IA32) $(BUILD_UEFI_AARCH64) $(BUILD_BIOS) +all: limine-version limine-enroll-config $(BUILD_UEFI_X86_64) $(BUILD_UEFI_IA32) $(BUILD_UEFI_AARCH64) $(BUILD_BIOS) $(MAKE) '$(call SHESCAPE,$(BINDIR))/limine-cd-efi.bin' $(call MKESCAPE,$(BINDIR))/limine-hdd.h: $(call MKESCAPE,$(BINDIR))/limine-hdd.bin @@ -98,6 +98,10 @@ $(call MKESCAPE,$(BINDIR))/limine-version: $(call MKESCAPE,$(BINDIR))/Makefile $ $(SED) 's/@LIMINE_VERSION@/@PACKAGE_VERSION@/g' <'$(call SHESCAPE,$(SRCDIR))/host/limine-version.c' >'$(call SHESCAPE,$(BINDIR))/limine-version.c' $(MAKE) -C '$(call SHESCAPE,$(BINDIR))' limine-version +$(call MKESCAPE,$(BINDIR))/limine-enroll-config: $(call MKESCAPE,$(BINDIR))/Makefile $(call MKESCAPE,$(SRCDIR))/host/limine-enroll-config.c + cp '$(call SHESCAPE,$(SRCDIR))/host/limine-enroll-config.c' '$(call SHESCAPE,$(BINDIR))/' + $(MAKE) -C '$(call SHESCAPE,$(BINDIR))' limine-enroll-config + $(call MKESCAPE,$(BINDIR))/Makefile: $(call MKESCAPE,$(SRCDIR))/host/Makefile $(call MKESCAPE,$(SRCDIR))/host/.gitignore $(MKDIR_P) '$(call SHESCAPE,$(BINDIR))' cp '$(call SHESCAPE,$(SRCDIR))/host/Makefile' '$(call SHESCAPE,$(SRCDIR))/host/.gitignore' '$(call SHESCAPE,$(BINDIR))/' @@ -110,6 +114,10 @@ limine-deploy: limine-version: $(MAKE) '$(call SHESCAPE,$(BINDIR))/limine-version' +.PHONY: limine-enroll-config +limine-enroll-config: + $(MAKE) '$(call SHESCAPE,$(BINDIR))/limine-enroll-config' + .PHONY: clean clean: limine-bios-clean limine-uefi-ia32-clean limine-uefi-x86-64-clean limine-uefi-aarch64-clean rm -rf '$(call SHESCAPE,$(BINDIR))' '$(call SHESCAPE,$(BUILDDIR))/stage1.stamp' @@ -146,6 +154,7 @@ endif install-strip: install-data $(INSTALL) -d '$(call SHESCAPE,$(DESTDIR)$(ACBINDIR))' $(INSTALL_PROGRAM) -s '$(call SHESCAPE,$(BINDIR))/limine-version' '$(call SHESCAPE,$(DESTDIR)$(ACBINDIR))/' + $(INSTALL_PROGRAM) -s '$(call SHESCAPE,$(BINDIR))/limine-enroll-config' '$(call SHESCAPE,$(DESTDIR)$(ACBINDIR))/' ifneq ($(BUILD_LIMINE_DEPLOY),no) $(INSTALL_PROGRAM) -s '$(call SHESCAPE,$(BINDIR))/limine-deploy' '$(call SHESCAPE,$(DESTDIR)$(ACBINDIR))/' endif @@ -154,6 +163,7 @@ endif install: install-data $(INSTALL) -d '$(call SHESCAPE,$(DESTDIR)$(ACBINDIR))' $(INSTALL_PROGRAM) '$(call SHESCAPE,$(BINDIR))/limine-version' '$(call SHESCAPE,$(DESTDIR)$(ACBINDIR))/' + $(INSTALL_PROGRAM) '$(call SHESCAPE,$(BINDIR))/limine-enroll-config' '$(call SHESCAPE,$(DESTDIR)$(ACBINDIR))/' ifneq ($(BUILD_LIMINE_DEPLOY),no) $(INSTALL_PROGRAM) '$(call SHESCAPE,$(BINDIR))/limine-deploy' '$(call SHESCAPE,$(DESTDIR)$(ACBINDIR))/' endif @@ -161,6 +171,7 @@ endif .PHONY: uninstall uninstall: rm -f '$(call SHESCAPE,$(DESTDIR)$(ACBINDIR))/limine-version' + rm -f '$(call SHESCAPE,$(DESTDIR)$(ACBINDIR))/limine-enroll-config' rm -f '$(call SHESCAPE,$(DESTDIR)$(ACBINDIR))/limine-deploy' rm -rf '$(call SHESCAPE,$(DESTDIR)$(ACDATAROOTDIR))/limine' rm -f '$(call SHESCAPE,$(DESTDIR)$(ACINCLUDEDIR))/limine.h' diff --git a/common/lib/config.c b/common/lib/config.c index a53320ff..4a275f7c 100644 --- a/common/lib/config.c +++ b/common/lib/config.c @@ -3,10 +3,17 @@ #include #include #include +#include #include #include #include #include +#include + +#define CONFIG_B2SUM_SIGNATURE "++CONFIG_B2SUM_SIGNATURE++" +#define CONFIG_B2SUM_EMPTY "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + +const char *config_b2sum = CONFIG_B2SUM_SIGNATURE CONFIG_B2SUM_EMPTY; static bool config_get_entry_name(char *ret, size_t index, size_t limit); static char *config_get_entry(size_t *size, size_t index); @@ -136,6 +143,29 @@ struct macro { static struct macro *macros = NULL; int init_config(size_t config_size) { + config_b2sum += sizeof(CONFIG_B2SUM_SIGNATURE) - 1; + + if (memcmp((void *)config_b2sum, CONFIG_B2SUM_EMPTY, 128) != 0) { + uint8_t out_buf[BLAKE2B_OUT_BYTES]; + blake2b(out_buf, config_addr, config_size - 2); + uint8_t hash_buf[BLAKE2B_OUT_BYTES]; + + for (size_t i = 0; i < BLAKE2B_OUT_BYTES; i++) { + hash_buf[i] = digit_to_int(config_b2sum[i * 2]) << 4 | digit_to_int(config_b2sum[i * 2 + 1]); + } + + if (memcmp(hash_buf, out_buf, BLAKE2B_OUT_BYTES) != 0) { + print("!!! CHECKSUM MISMATCH FOR CONFIG FILE !!!\n"); + print("If you do not know what this means, ANSWER WITH 'N' NOW!\n"); + print("Proceed with boot anyways? [y/N]: "); + if (getchar() != 'y') { + print("\n"); + panic(true, "Checksum mismatch for config file"); + } + print("\n"); + } + } + // add trailing newline if not present config_addr[config_size - 2] = '\n'; diff --git a/host/.gitignore b/host/.gitignore index 9b9a44b2..059eb254 100644 --- a/host/.gitignore +++ b/host/.gitignore @@ -2,3 +2,5 @@ limine-deploy limine-deploy.exe limine-version limine-version.exe +limine-enroll-config +limine-enroll-config.exe diff --git a/host/Makefile b/host/Makefile index 1ee8b783..de20a330 100644 --- a/host/Makefile +++ b/host/Makefile @@ -6,7 +6,7 @@ PREFIX ?= /usr/local CFLAGS ?= -g -O2 -pipe -Wall -Wextra .PHONY: all -all: limine-deploy limine-version +all: limine-deploy limine-version limine-enroll-config .PHONY: install-data install-data: all @@ -26,20 +26,26 @@ install: install-data $(INSTALL) -d '$(DESTDIR)$(PREFIX)/bin' $(INSTALL) limine-deploy '$(DESTDIR)$(PREFIX)/bin/' $(INSTALL) limine-version '$(DESTDIR)$(PREFIX)/bin/' + $(INSTALL) limine-enroll-config '$(DESTDIR)$(PREFIX)/bin/' .PHONY: install-strip install-strip: install-data $(INSTALL) -d '$(DESTDIR)$(PREFIX)/bin' $(INSTALL) -s limine-deploy '$(DESTDIR)$(PREFIX)/bin/' $(INSTALL) -s limine-version '$(DESTDIR)$(PREFIX)/bin/' + $(INSTALL) -s limine-enroll-config '$(DESTDIR)$(PREFIX)/bin/' .PHONY: clean clean: rm -f limine-deploy limine-deploy.exe rm -f limine-version limine-version.exe + rm -f limine-enroll-config limine-enroll-config.exe limine-deploy: limine-deploy.c limine-hdd.h $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -std=c99 -D__USE_MINGW_ANSI_STDIO limine-deploy.c $(LIBS) -o $@ limine-version: limine-version.c $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -std=c99 -D__USE_MINGW_ANSI_STDIO limine-version.c $(LIBS) -o $@ + +limine-enroll-config: limine-enroll-config.c + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -std=c99 -D__USE_MINGW_ANSI_STDIO limine-enroll-config.c $(LIBS) -o $@ diff --git a/host/limine-enroll-config.c b/host/limine-enroll-config.c new file mode 100644 index 00000000..c7e0410d --- /dev/null +++ b/host/limine-enroll-config.c @@ -0,0 +1,92 @@ +#include +#include +#include +#include + +#define CONFIG_B2SUM_SIGNATURE "++CONFIG_B2SUM_SIGNATURE++" + +int main(int argc, char *argv[]) { + int ret = 1; + + char *bootloader = NULL; + FILE *bootloader_file = NULL; + + if (argc <= 2) { + fprintf(stderr, "usage: %s <128-byte BLAKE2B of config file>\n", argv[0]); + goto cleanup; + } + + if (strlen(argv[2]) != 128) { + fprintf(stderr, "ERROR: BLAKE2B specified is not 128 characters long\n"); + goto cleanup; + } + + bootloader_file = fopen(argv[1], "r+b"); + if (bootloader_file == NULL) { + perror("ERROR"); + goto cleanup;; + } + + if (fseek(bootloader_file, 0, SEEK_END) != 0) { + perror("ERROR"); + goto cleanup; + } + size_t bootloader_size = ftell(bootloader_file); + rewind(bootloader_file); + + bootloader = malloc(bootloader_size); + if (bootloader == NULL) { + perror("ERROR"); + goto cleanup; + } + + if (fread(bootloader, bootloader_size, 1, bootloader_file) != 1) { + perror("ERROR"); + goto cleanup; + } + + char *checksum_loc = NULL; + size_t checked_count = 0; + const char *config_b2sum_sign = CONFIG_B2SUM_SIGNATURE; + for (size_t i = 0; i < bootloader_size; i++) { + if (bootloader[i] != config_b2sum_sign[checked_count]) { + checked_count = 0; + continue; + } + + checked_count++; + + if (checked_count == sizeof(CONFIG_B2SUM_SIGNATURE) - 1) { + checksum_loc = &bootloader[i + 1]; + break; + } + } + + if (checksum_loc == NULL) { + fprintf(stderr, "ERROR: Checksum location not found in provided executable\n"); + goto cleanup; + } + + memcpy(checksum_loc, argv[2], 128); + + if (fseek(bootloader_file, 0, SEEK_SET) != 0) { + perror("ERROR"); + goto cleanup; + } + if (fwrite(bootloader, bootloader_size, 1, bootloader_file) != 1) { + perror("ERROR"); + goto cleanup; + } + + fprintf(stderr, "Config file BLAKE2B successfully enrolled!\n"); + ret = 0; + +cleanup: + if (bootloader != NULL) { + free(bootloader); + } + if (bootloader_file != NULL) { + fclose(bootloader_file); + } + return ret; +}