noahbliss / mortar Goto Github PK
View Code? Open in Web Editor NEWFramework to join Linux's physical security bricks.
License: GNU General Public License v3.0
Framework to join Linux's physical security bricks.
License: GNU General Public License v3.0
An FYI to readers and a to-do note for me. The certs with .crt in /etc/mortar/private are in PEM format even though the extension would imply they are DER format.
If the secureboot key install script does not work, you will need to install the db, KEK, and PK through the BIOS. Most BIOS implementations only accept DER formatted keys.
cp /etc/mortar/private/PK.crt PK.pem
openssl x509 -in PK.pem -outform der -out PK.crt
And so on.
Hello,
Is it possible to use a similar structure to support sedutil of LUKS?
For example, leave ESP partition read-only and unecrypted, and store password required to decrypt locking range for the main partition in TPM? If so, what additions would be needed in mortar?
Regards,
Alex
cmdline.conf is not updated with the new kernel version/path during an upgrade. This results in an incorrect version reported. So far I haven't run into any noticeable issues but tracking this for later resolution.
Note to self that the community seems to be deprecating sbsign for pesign.
Note to self to investigate using the shred
command if the system has it when we are performing the step 3 stage. Practical risk of not using shred should be negligible, we're already using a ramdisk, but if we have it, why not. :shrug:
Step 3 with TPM binding asks for the LUKS passphrase twice. Writing this to remind myself to investigate ways to only ask once. Maybe add some logic in there to test it before using it too.
I identified two things in your code organization that I would call problems, but maybe they are ok for you current project size. I would just use more sophisticated methods, because it is a security related project.
1.)
Running ./0-initialsetup-prereqinstall.sh
is an unusual way to use a command line application. I would rather see mortar --initial-setup
or something like that. Actually I think the best applications ask for user input instead of expecting it.
2.)
If you want to support multiple operating systems or multiple TPM versions, then you need abstractions and polymorphism at a certain level. In practice this means whenever you have multiple implementations of the same concept you come up with a general function name, something like doStuff
. You move the different implementations of doStuff
to different files and load them from there. So for example when you have tpm 1.2 then you import tpm1.2/doStuff.sh
and when you have tpm 2.0 then you import tpm2.0/doStuff.sh
. After you collected the configuration from the user in 1.) you can select the right implementations and import those files. After that you just call a general code, which calls functions like doThisStuff()
without knowing the implementation details. A simple example of these can be the following:
source run.sh
run.sh
#!/usr/bin/env bash
run(){
configure
importFunctions
main
}
configure(){
isDebian=$(($RANDOM%2))
}
importFunctions(){
if ((isDebian)); then
source "./debian.sh"
else
source "./arch.sh"
fi
source "./main.sh"
}
run
main.sh
#!/usr/bin/env bash
main(){
doStuff
doOtherStuff
}
debian.sh
#!/usr/bin/env bash
doStuff(){
echo "debian code running"
}
doOtherStuff(){
echo "blah blah"
}
arch.sh
#!/usr/bin/env bash
doStuff(){
echo "arch code running"
}
doOtherStuff(){
echo "nooooooo yes"
}
As of the function names you can typically name them based on the comments you have in your code. For example here: https://github.com/noahbliss/mortar/blob/master/0-initialsetup-prereqinstall.sh#L14 you have Figure out our distribuition.
in comment and you can have a function with figureOutOurDistribution
name instead. You can call that function from the main
. If the main
grows too complex then you group functions for example in your case 0-initialsetup-prereqinstall.sh
is the way of grouping. You just define initialSetup
which calls the initial setup related functiions. You can keep them in a separate file and source it from importFunctions
or from main
if you don't want to scroll that much.
3.)
After you have 2.) you can write automated tests against the general code and mock out the OS or TPM version specific implementations. You will need a test runner instead of the application runner too. This way you can test maybe half of the code automagically. You can write integration tests for the rest if you want to, but I guess that would be hard even with virtualization.
source test.sh
test.sh
source "./mock.sh"
source "./main.sh"
testMain(){
failures=0
testIfDoStuffCalled
testIfDoOtherStuffCalled
if ((failures)); then
echo "$failures tests failed"
else
echo "success"
fi
}
testIfDoStuffCalled(){
probeDoStuffCalled=0
main
if ((probeDoStuffCalled!=1)); then
echo "doStuff should be called exactly once"
((failures++))
fi
}
testIfDoOtherStuffCalled(){
probeDoOtherStuffCalled=0
main
if ((probeDoOtherStuffCalled!=1)); then
echo "doOtherStuff should be called exactly once"
((failures++))
fi
}
testMain
mock.sh
#!/usr/bin/env bash
doStuff(){
((probeDoStuffCalled++))
}
doOtherStuff(){
((probeDoOtherStuffCalled++))
}
Not sure how much general code you will have that you can use with all OS types and all TPM versions, but if it is not just a few lines it is worth testing I think.
On first run, there is no old key to wipe, this causes cryptsetup to panic. This does not hinder the remaining execution of the script or cause practical malfunction, but doesn't look very nice.
This individual does not understand the basic trappings of how the internet or encryption works.
There's absolutely no way in mankind that they're imbued with the qualities necessary to safely construct a project that cannot be easily bypassed and/or compromised.
If this child has done the initial work of at least figuring out the necessary steps / skeleton structure for a secure boot process, then I suppose that at least this can be considered a benefit.
Do not rely on this dipshit for anything meaningful though - go to the Arch Linux and refer to the notes that they have there. They are legitimate developers that actually know what the fuck they're talking about.
This person is a script kiddie (literally), with a middle schooler's undertanding of the internet and how it works. I will more than likely write up about this individual on my blog and publish it so that all can be warned to not waste their time with what could amount to garden variety malware (you know, because this kid does not understand how the internet works - he's never even heard of the IETF! Does not know how DNS works!! Thinks its some magic fairy in the sky that bestows the correct IP address mappings!
Everyone who read this message is being fucking saved. You're welcome and you've been duly warned.
When installing debian from the debian-11.7.0-amd64-netinst.iso
ISO and choosing standard system utilities
and ssh server
only, there is a missing package that the mortar-compilesigninstall
script does not install or check the availability of (gawk
):
root@debianvm:/boot# mortar-compilesigninstall /boot/vmlinuz-5.10.0-26-amd64 /boot/initrd.img-5.10.0-26 -amd64 --install-entry
/usr/local/sbin/mortar-compilesigninstall: line 51: gawk: command not found
/usr/local/sbin/mortar-compilesigninstall: line 52: 16#: invalid integer constant (error token is "16#" )
/usr/local/sbin/mortar-compilesigninstall: line 54: gawk: command not found
/usr/local/sbin/mortar-compilesigninstall: line 55: osrel_offs + - osrel_offs % : syntax error: operan d expected (error token is "% ")
/usr/local/sbin/mortar-compilesigninstall: line 57: cmdline_offs + - cmdline_offs % : syntax error: op erand expected (error token is "% ")
/usr/local/sbin/mortar-compilesigninstall: line 59: splash_offs + - splash_offs % : syntax error: oper and expected (error token is "% ")
/usr/local/sbin/mortar-compilesigninstall: line 61: initrd_offs + - initrd_offs % : syntax error: oper and expected (error token is "% ")
/usr/local/sbin/mortar-compilesigninstall: line 63: linux_offs + - linux_offs % : syntax error: operan d expected (error token is "% ")
Created /boot/efi/EFI/mortarsecureboot-linux.efi.unsigned
Signing...
warning: gap in section table:
.initrd : 0x00000740 - 0x01f9ad40,
.text : 0x01f9ae00 - 0x01fa2a00,
gaps in the section table may result in different checksums
warning: data remaining[40231744 vs 40241503]: gaps between PE/COFF sections?
warning: gap in section table:
.initrd : 0x00000740 - 0x01f9ad40,
.text : 0x01f9ae00 - 0x01fa2a00,
gaps in the section table may result in different checksums
warning: data remaining[40231744 vs 40241504]: gaps between PE/COFF sections?
Signing Unsigned original image
Created signed /boot/efi/EFI/mortarsecureboot-linux.efi
Attempting to install new efi file into UEFI boot menu...
BootCurrent: 0004
Timeout: 0 seconds
BootOrder: 0005,0004,0000,0001,0002,0003
Boot0000* UiApp
Boot0001* UEFI VBOX CD-ROM VB2-01700376
Boot0002* UEFI VBOX HARDDISK VBf882a982-a83450b1
Boot0003 EFI Internal Shell
Boot0004* debian
Boot0005* Mortar Secureboot Linux
Added boot entry.
root@debianvm:/boot#
If I install gawk
and run the command again, I get the following:
root@debianvm:/boot# mortar-compilesigninstall /boot/vmlinuz-5.10.0-26-amd64 /boot/initrd.img-5.10.0-26-amd64 --install-entry
Created /boot/efi/EFI/mortarsecureboot-linux.efi.unsigned
Found old signed file. Backing up to /boot/efi/EFI/mortarsecureboot-linux.efi.old.efi
Signing...
warning: data remaining[40231936 vs 40241503]: gaps between PE/COFF sections?
warning: data remaining[40231936 vs 40241504]: gaps between PE/COFF sections?
Signing Unsigned original image
Created signed /boot/efi/EFI/mortarsecureboot-linux.efi
Attempting to install new efi file into UEFI boot menu...
efibootmgr: ** Warning ** : Boot0005 has same label Mortar Secureboot Linux
BootCurrent: 0004
Timeout: 0 seconds
BootOrder: 0006,0005,0004,0000,0001,0002,0003
Boot0000* UiApp
Boot0001* UEFI VBOX CD-ROM VB2-01700376
Boot0002* UEFI VBOX HARDDISK VBf882a982-a83450b1
Boot0003 EFI Internal Shell
Boot0004* debian
Boot0005* Mortar Secureboot Linux
Boot0006* Mortar Secureboot Linux
Added boot entry.
root@debianvm:/boot#
Could we add a check for gawk
or add it to the debian pre-reqs installation script? I imagine a lot of people who are installing debian with the intend of then installing Proxmox on top, are going to use the minimal install ISO and make the same tasksel
selections as mine.
Installing and configuring mortar works perfectly with Proxmox 5.15.* kernels, however, using the latest 5.19 and 6.1 kernels for Proxmox result in boot hang up.
Debian's Live Installer has changed the way Debian interacts with LUKS volumes. Manjaro similarly uses this technique. It configures the system with an encrypted boot volume and uses Grub to perform the initial unlocking. After Grub unlocks, it uses a LUKS key on disk (in the root of the drive and also included in the initramfs) to re-unlock it automatically after the Grub hand-off to the Linux kernel.
Obviously this throws a wrench in how Mortar interfaces with the system. I'm working on a solution. So far having the /boot location already encrypted does save us a few steps, and the current code already overwrites the Debian "hand-off key" slot, but looks like we need to fiddle with the crypttab file a little bit at least.
Recently, I've noticed mortar failing to automatically unlock my LUKS partition at boot. Since this occasionally happens after upgrading the kernel, I decided to re-run both mkinitcpio -P
and mortar-compilesigninstall
. However, when I run mortar-compilesigninstall
now, I am greeted with the following console output:
objcopy: /boot/EFI/mortarsecureboot-linux.efi.unsigned:.osrel: section below image base
objcopy: /boot/EFI/mortarsecureboot-linux.efi.unsigned:.cmdline: section below image base
objcopy: /boot/EFI/mortarsecureboot-linux.efi.unsigned:.linux: section below image base
objcopy: /boot/EFI/mortarsecureboot-linux.efi.unsigned:.initrd: section below image base
Created /boot/EFI/mortarsecureboot-linux.efi.unsigned
Found old signed file. Backing up to /boot/EFI/mortarsecureboot-linux.efi.old.efi
Signing...
Signing Unsigned original image
Created signed /boot/EFI/mortarsecureboot-linux.efi
Needless to say, the newly generated EFI file does not unlock the drive properly. Did something change with a recent kernel? Admittedly, I have not tested this on a fresh install, so if that would be worthwhile I'd be happy to try it out. I wasn't sure if this was something others were seeing or if it was unique to my install.
Some distros *cough* proxmox *cough* rely on out-of-tree kernel modules. It appears this can render a failure to boot situation. This is remedied by disabling secureboot (of course breaking Mortar). It appears it may be possible to sign these kernel modules with the db cert generated by mortar and stored in /etc/mortar/private.
cat /proc/keys
shows that as a trusted cert. Will update with details later.
Upon failing to write Secure Boot keys, the 2-installsecurebootkeys.sh
script tries to print what it failed to install but instead shows nothing.
Test System:
debian-11.7.0-amd64-netinst.iso
ISO, with 'standard system utilities' and 'ssh server' selected during installation.Command output:
root@debianvm:~/mortar# ./2-installsecurebootkeys.sh
Cannot write to db, wrong filesystem permissions
Failed to install . Is your secureboot in the BIOS configured for audit mode?
There appears to be an issue with bleeding edge distributions when performing automatic unlock with Clevis. This error happens during boot time during the TPM validation phase.
The PCR values are as expected/same as when the key was bound, but the disk is not automatically unlocked. Specifically we are getting the error:
/bin/clevis-decrypt: line 49: /dev/fd/62 No such file or directory
Will update this issue and push a fix after further investigation.
I was having issues auto provisioning Secure Boot keys on a debian system using the script, so I tried to manually provision the PK etc. that the script has generated. However, the system firmware setup utility rejects the files. Example below.
If it helps troubleshooting, according to page (20)26 here, Certificates in the DER format and SHA-256 hashes in the HSH format are accepted.
I can't find a whole lot of info. Any help would be appreciated. I know there are others who use this and similar Dell systems who want to take advantage of Mortar.
This is going to be accepted as a "known issue" for now. Packages and scripts that update the initramfs/initrd file, do have the necessary unlock binaries and scripts included, but they do not prompt the regeneration of the EFI file. It is only after manually running mortar-compilesigninstall that the efi is updated.
This issue has limited impact as the most significant updates, those to the kernel, do invoke the EFI generation. I think I will work to make the mortar-compilesigninstall script a little smarter to relieve some of the inconvenience.
On a fresh debian 12 libvirt virtual machine (wanted to test before deciding to switch from fedora)
getting error on line 61 when running script
1-generatesecurebootkeys.sh
Line 61: Cryptsetup: command not found
I am not sure if this is intentional, but I see sometimes bin/bash and bin/sh in the code. Afaik bin/sh can be dash too on some systems, so it would be better to use bash only unless you have a good reason to use sh.
By default mortar uses PCRs 1 and 7, but there are some other important PCRs which should get used if handled properly by the BIOS/UEFI. There's just a short note in the mortar.env that the PCRs are configurable and an optional step in the installation example (README.md).
The documentation could be extended to describe this topic more precise and to inform the user of the importance of some additional PCR values. For example as a more prominent step within the example or some additional topic in the SECURITY.md?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.