|
| 1 | +#!/usr/bin/env perl |
| 2 | +# vim: softtabstop=2 shiftwidth=2 expandtab |
| 3 | + |
| 4 | +# This script can be used to sign ZFSBootMenu EFI images for use with Secure |
| 5 | +# Boot. It works with both `sbctl` and `sbsigntools`. |
| 6 | +# |
| 7 | +# Installing this script as a post-run hook for generate-zbm(5) will allow |
| 8 | +# automatic signing of new images as they are produced by generate-zbm(8). To |
| 9 | +# do so, make sure that the `Global` section of the generate-zbm configuration |
| 10 | +# file includes a `PostHooksDir` key with a value that refers to an existing |
| 11 | +# directory in your filesystem. Then, save this script in the named directory |
| 12 | +# and set its executable bit. |
| 13 | +# |
| 14 | +# Run-time configuration for this hook is loaded from the ZFSBootMenu |
| 15 | +# configuration file at `/etc/zfsbootmenu/config.yaml`. Add a `SecureBoot` |
| 16 | +# section, which will be ignored by `generate-zbm`, to the file: |
| 17 | +# |
| 18 | +# SecureBoot: |
| 19 | +# SignBackup: true |
| 20 | +# DeleteUnsigned: false |
| 21 | +# SignMethod: sbctl |
| 22 | +# KeyDir: /etc/sbkeys |
| 23 | +# |
| 24 | +# The configuration keys should be self-explanatory. |
| 25 | + |
| 26 | +print "---------- ZBM-Sign ----------\n"; |
| 27 | +use feature 'say'; |
| 28 | +use strict; |
| 29 | +use warnings; |
| 30 | +use File::Find; |
| 31 | +use YAML::PP; |
| 32 | + |
| 33 | +my @EFIBins; |
| 34 | +my $Unsigned; |
| 35 | +my $SignMethod; |
| 36 | + |
| 37 | +my $ypp = YAML::PP->new( boolean => 'boolean' ); |
| 38 | +my $config = $ypp->load_file('/etc/zfsbootmenu/config.yaml'); |
| 39 | +my $EFI = $config->{EFI}; |
| 40 | +my $EFI_Enabled = $EFI->{Enabled}; |
| 41 | +if ( !$EFI_Enabled ) { |
| 42 | + die "EFI images are disabled! Nothing to sign!"; |
| 43 | +} |
| 44 | + |
| 45 | +my $Global = $config->{Global}; |
| 46 | +my $ESP = $Global->{BootMountPoint}; |
| 47 | + |
| 48 | +my $SecureBoot = $config->{SecureBoot} or die "No config found, please edit /etc/zfsbootmenu/config.yaml"; |
| 49 | +my $ZBM = "$ESP/EFI/zbm"; |
| 50 | +my $KeyDir = $SecureBoot->{KeyDir}; |
| 51 | +my $DeleteUnsigned = $SecureBoot->{DeleteUnsigned}; |
| 52 | +my $SignBackups = $SecureBoot->{SignBackup}; |
| 53 | +$SignMethod = $SecureBoot->{SignMethod}; |
| 54 | + |
| 55 | +opendir my $ZBM_dir, $ZBM |
| 56 | + or die "Cannot open ZBM dir: $ZBM"; |
| 57 | + |
| 58 | +if ($SignBackups) { |
| 59 | + @EFIBins = grep { !/signed\.efi$/i and /\.efi/i } readdir $ZBM_dir; |
| 60 | +} else { |
| 61 | + @EFIBins = grep { !/signed\.efi$/i and !/backup/i and /\.efi/i } readdir $ZBM_dir; |
| 62 | +} |
| 63 | + |
| 64 | +say "Found: @EFIBins"; |
| 65 | +if ( !$SignMethod ) { |
| 66 | + die "No sign method found"; |
| 67 | +} |
| 68 | +for (@EFIBins) { |
| 69 | + |
| 70 | + say "\nSigning $_"; |
| 71 | + |
| 72 | + if ( $SignMethod eq "sbctl" ) { |
| 73 | + system "sbctl sign $ZBM/$_"; |
| 74 | + } elsif ( $SignMethod eq "sbsign" ) { |
| 75 | + $Unsigned = substr( $_, 0, -4 ); |
| 76 | + system "sbsign --key $KeyDir/DB.key --cert $KeyDir/DB.crt $ZBM/$_ --output $ZBM/$Unsigned-signed.efi"; |
| 77 | + } else { |
| 78 | + die "Sign method $SignMethod not valid."; |
| 79 | + } |
| 80 | + |
| 81 | + if ( $DeleteUnsigned && $SignMethod eq "sbctl" ) { |
| 82 | + say "sbctl signs in place, not deleting $_"; |
| 83 | + } elsif ( $DeleteUnsigned && $SignMethod ne "sbctl" ) { |
| 84 | + say "Deleting unsigned $_"; |
| 85 | + system "rm $ZBM/$_"; |
| 86 | + } |
| 87 | +} |
| 88 | +print "---------- FINISHED ----------\n"; |
0 commit comments