From 1a4a912849f100c9024088df8a1cad3fb1379f23 Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Fri, 19 Jan 2024 15:49:06 -0500 Subject: [PATCH] efibootmgr: add support for listing cryptographic signature types. Since UEFI 2.2, firmware has provided a list of supported signature types for Secure Boot binaries in a global variable named "SignatureSupport". This patch adds a new command line flag to efibootmgr, "--list-signature-types" ("-s") which collects that information from the firmware and displays it to the user, either by symbolic name if libefivar knows about that signature type or by GUID if it does not. On the system in front of me, that looks something like this: random:efibootmgr/signaturesupport$ ./src/efibootmgr -s x509_sha256 x509_sha384 x509_sha512 sha256 x509_cert rsa2048 rsa2048_sha256 rsa2048_sha1 external_management random:efibootmgr/signaturesupport$ ./src/efibootmgr -s -v x509_sha256 3bd2a492-96c0-4079-b420-fcf98ef103ed x509_sha384 7076876e-80c2-4ee6-aad2-28b349a6865b x509_sha512 446dbf63-2502-4cda-bcfa-2465d2b0fe9d sha256 c1c41626-504c-4092-aca9-41f936934328 x509_cert a5c059a1-94e4-4aa7-87b5-ab155c2bf072 rsa2048 3c5766e8-269c-4e34-aa14-ed776e85b3b6 rsa2048_sha256 e2b36190-879b-4a3d-ad8d-f2e7bba32784 rsa2048_sha1 67f8444f-8743-48f1-a328-1eaab8736080 external_management 452e8ced-dfff-4b8c-ae01-5118862e682c random:efibootmgr/signaturesupport$ Signed-off-by: Peter Jones --- src/efibootmgr.8.in | 33 ++++++++++++++++++- src/efibootmgr.c | 68 +++++++++++++++++++++++++++++++++++++++- src/include/efibootmgr.h | 1 + 3 files changed, 100 insertions(+), 2 deletions(-) diff --git a/src/efibootmgr.8.in b/src/efibootmgr.8.in index bab5b23..ed542e4 100644 --- a/src/efibootmgr.8.in +++ b/src/efibootmgr.8.in @@ -4,7 +4,7 @@ efibootmgr \- change the UEFI Boot Manager configuration .SH SYNOPSIS -\fBefibootmgr\fR [ \fB-a\fR ] [ \fB-A\fR ] [ \fB-b \fIXXXX\fB\fR ] [ \fB-B\fR ] [ \fB-c\fR ] [ \fB-d \fIDISK\fB\fR ] [ \fB-D\fR ] [ \fB-e \fI1|3|-1\fB\fR ] [ \fB-E \fINUM\fB\fR ] [ \fB--full-dev-path\fR | \fB--file-dev-path\fR ] [ \fB-f\fR ] [ \fB-F\fR ] [ \fB-g\fR ] [ \fB-i \fINAME\fB\fR ] [ \fB-l \fINAME\fB\fR ] [ \fB-L \fILABEL\fB\fR ] [ \fB-m \fIt|f\fB\fR ] [ \fB-M \fIX\fB\fR ] [ \fB-n \fIXXXX\fB\fR ] [ \fB-N\fR ] [ \fB-o \fIXXXX\fB,\fIYYYY\fB,\fIZZZZ\fB\fR\fI ...\fR ] [ \fB-O\fR ] [ \fB-p \fIPART\fB\fR ] [ \fB-q\fR ] [ \fB-r\fR | \fB-y\fR ] [ \fB-t \fIseconds\fB\fR ] [ \fB-T\fR ] [ \fB-u\fR ] [ \fB-v\fR ] [ \fB-V\fR ] [ \fB-@ \fIfile\fB\fR ] +\fBefibootmgr\fR [ \fB-a\fR ] [ \fB-A\fR ] [ \fB-b \fIXXXX\fB\fR ] [ \fB-B\fR ] [ \fB-c\fR ] [ \fB-d \fIDISK\fB\fR ] [ \fB-D\fR ] [ \fB-e \fI1|3|-1\fB\fR ] [ \fB-E \fINUM\fB\fR ] [ \fB--full-dev-path\fR | \fB--file-dev-path\fR ] [ \fB-f\fR ] [ \fB-F\fR ] [ \fB-g\fR ] [ \fB-i \fINAME\fB\fR ] [ \fB-l \fINAME\fB\fR ] [ \fB-L \fILABEL\fB\fR ] [ \fB-m \fIt|f\fB\fR ] [ \fB-M \fIX\fB\fR ] [ \fB-n \fIXXXX\fB\fR ] [ \fB-N\fR ] [ \fB-o \fIXXXX\fB,\fIYYYY\fB,\fIZZZZ\fB\fR\fI ...\fR ] [ \fB-O\fR ] [ \fB-p \fIPART\fB\fR ] [ \fB-q\fR ] [ \fB-r\fR | \fB-y\fR ] [ \fB-s\fR ] [ \fB-t \fIseconds\fB\fR ] [ \fB-T\fR ] [ \fB-u\fR ] [ \fB-v\fR ] [ \fB-V\fR ] [ \fB-@ \fIfile\fB\fR ] .SH "DESCRIPTION" .PP @@ -130,6 +130,11 @@ Quiet mode - suppresses output. \fB-r | --driver\fR Operate on Driver#### variables instead of Boot#### variables. .TP +\fB-s | --list-signature-types\fR +List cryptographic signature types supported on this machine and exit. If in +verbose mode, the symbolic name as well as the raw GUID will be displayed. +Consult the UEFI Specification for more details. +.TP \fB-t | --timeout \fIseconds\fB\fR Boot Manager timeout, in \fIseconds\fR\&. .TP @@ -223,6 +228,32 @@ entry 4 and remove it from the BootOrder. A system administrator wants to create a boot option to network boot. You create the boot entry with: \fBefibootmgr -c -i eth0 -L netboot [ -l '\\filename.efi' ]\fR +.SS "Displaying the supported cryptographic signature types" +\fR +.nf +.B +[root@localhost ~]# efibootmgr -s +x509_sha256 +x509_sha384 +x509_sha512 +sha256 +x509_cert +rsa2048 +rsa2048_sha256 +rsa2048_sha1 +external_management +.B +[root@localhost ~]# efibootmgr -s -v +x509_sha256 3bd2a492-96c0-4079-b420-fcf98ef103ed +x509_sha384 7076876e-80c2-4ee6-aad2-28b349a6865b +x509_sha512 446dbf63-2502-4cda-bcfa-2465d2b0fe9d +sha256 c1c41626-504c-4092-aca9-41f936934328 +x509_cert a5c059a1-94e4-4aa7-87b5-ab155c2bf072 +rsa2048 3c5766e8-269c-4e34-aa14-ed776e85b3b6 +rsa2048_sha256 e2b36190-879b-4a3d-ad8d-f2e7bba32784 +rsa2048_sha1 67f8444f-8743-48f1-a328-1eaab8736080 +external_management 452e8ced-dfff-4b8c-ae01-5118862e682c +.fi .SH "BUGS" .PP Please direct any bugs, features, patches, etc. to the Red Hat bootloader team at https://github.com/rhboot/efibootmgr \&. diff --git a/src/efibootmgr.c b/src/efibootmgr.c index 3ba4d1b..0094e05 100644 --- a/src/efibootmgr.c +++ b/src/efibootmgr.c @@ -1390,6 +1390,61 @@ show_mirror(void) } } +static int +list_supported_signature_types(void) +{ + var_entry_t entry = { 0, }; + int rc; + size_t n_entries; + unsigned int i; + + rc = efi_get_variable(EFI_GLOBAL_GUID, "SignatureSupport", + &entry.data, &entry.data_size, &entry.attributes); + if (rc == ENOENT) { + warning("Firmware does not support any signature types"); + return 0; + } + if (rc < 0) { + efi_error("efi_get_variable failed"); + return -1; + } + if (entry.data_size % sizeof(efi_guid_t) != 0) + warning("SignatureSupport variable has suspicious size %zu", + entry.data_size); + + n_entries = entry.data_size / sizeof(efi_guid_t); + + for (i = 0; i < n_entries; i++) { + efi_guid_t *guid = &((efi_guid_t *)entry.data)[i]; + char *guidname = NULL; + + rc = efi_guid_to_name(guid, &guidname); + if (rc < 0) { + efi_error("efi_guid_to_name failed"); + return -1; + } + printf("%s", guidname); + free(guidname); + guidname = NULL; + + if (verbose >= 1) { + rc = efi_guid_to_str(guid, &guidname); + + if (rc < 0) { + putchar('\n'); + efi_error("efi_guid_to_str failed"); + return -1; + } + printf(" %s", guidname); + free(guidname); + } + + putchar('\n'); + } + + return 0; +} + static void usage() { @@ -1494,6 +1549,7 @@ parse_opts(int argc, char **argv) {"part", required_argument, 0, 'p'}, {"quiet", no_argument, 0, 'q'}, {"driver", no_argument, 0, 'r'}, + {"list-signature-types", no_argument, 0, 's'}, {"timeout", required_argument, 0, 't'}, {"delete-timeout", no_argument, 0, 'T'}, {"unicode", no_argument, 0, 'u'}, @@ -1507,7 +1563,7 @@ parse_opts(int argc, char **argv) }; c = getopt_long(argc, argv, - "aAb:BcCd:De:E:fFgi:I:kl:L:m:M:n:No:Op:qrt:Tuv::Vwy@:h", + "aAb:BcCd:De:E:fFgi:I:kl:L:m:M:n:No:Op:qrst:Tuv::Vwy@:h", long_options, &option_index); if (c == -1) break; @@ -1713,6 +1769,9 @@ parse_opts(int argc, char **argv) case 'r': opts.driver = 1; break; + case 's': + opts.list_supported_signature_types = 1; + break; case 't': rc = sscanf(optarg, "%u", &num); if (rc == 1) { @@ -1807,6 +1866,13 @@ main(int argc, char **argv) verbose = opts.verbose; + if (opts.list_supported_signature_types) { + int rc = list_supported_signature_types(); + if (rc < 0) + errorx(40, "Could not read and display supported signature types\n"); + exit(0); + } + if (opts.sysprep && opts.driver) errx(25, "--sysprep and --driver may not be used together."); diff --git a/src/include/efibootmgr.h b/src/include/efibootmgr.h index 9737b0d..34fa56c 100644 --- a/src/include/efibootmgr.h +++ b/src/include/efibootmgr.h @@ -92,6 +92,7 @@ typedef struct { unsigned int driver:1; unsigned int sysprep:1; unsigned int explicit_label:1; + unsigned int list_supported_signature_types:1; short int timeout; uint16_t index; } efibootmgr_opt_t;