Skip to content

Latest commit

 

History

History
854 lines (509 loc) · 46.1 KB

system.org

File metadata and controls

854 lines (509 loc) · 46.1 KB

How I set up my computers, and why.

Principles of Security, Freedom, and Utility

This config makes a lot of choices about certain systems over other systems. This is an attempt to outline the general basis for these choices,

Three Definitions of “Secure”

What does it mean for something to be secure? There seem to be, in conventional discussion about the subject, three different positions.

Liberal Consequential Security

This position is that security is fundamentally about risk of harm. That is, if two pieces of financial software are being compared, the more secure choice is the one with less risk of loss of funds, as evaluated by their user on the basis of all information available to him.

This is an attractive position, not least to those who are ethically consequentiallist, but simple examination quickly throws it into absurdity—it appears its attraction may well be due to confusion with a distinct usage of the word, e.g. “The right of the people to be secure in their persons, houses, papers, and effects against unreasonable searches and seizures shall not be violated…”

Security is Too Important to Wager on Induction

This position commits one to a particular solution to the problem of induction, or uncertain reasoning—not by any means philosophically settled—before one can even begin to evaluate software security. The most popular position in the current moment is that subjectivist Bayesian probability theory founds this kind of reasoning. For illustration, let’s say the consequentialist agrees. This means that, when writing software, security is entirely a function of all knowledge that each one of its users has. So, in particular, the security of the piece of software varies from user-to-user, depends on things such as “this was written by a good, upstanding Christan boy.” Most damningly (mirroring Frege’s rebuttal of mathematical psychologism), this suggests that the proper methodology for writing secure software is running inverse design algorithms based on A/B statistical testing of the target population’s risk estimates of each line of code. As this is basically the opposite of secure design methodology, it would seem that at least subjectivist Bayesian consequential security is untenable.

Of course, this doesn’t cover the other possible foundations of uncertain reasoning, but it illustrates the problem of depending on any such foundation in the analysis of security—they’re foundations built on soft sand, for the time being, and it seems very unlikely that any possible future resolution (they’re all statistical of some character) will result in a perscription for ensuring security consistent in any way with how it’s actually practiced.

If there were no other alternative foundations for reasoning, or no other interpretations of security that exploit those foundations, then it’d be the best we could do…unfortunately, there are.

The Obscure Simply is not Secure

If there exists a vulnerability in some software, but no one knows about it yet, obfuscatory steps that make it harder discover that vulnerability do unquestionably decrease the risk that someone will find and subsequently exploit it to the loss of its users. Accordingly, this position cannot to anything but endorse security through obscurity, a position so unpopular as to be called fallacy.

Strict Ontological Security

These people believe that security is solely a function of the existence or non-existence of exploitable flaws in the entity in question. An attractive way to fix the shortcomings of the consequential approach, it nevertheless is similarly lacking.

Who Decides?

Consider the following scenario: a company offers two encryption schemes. The first is a “Free” tier, and accordingly is based on objectively worse data-hiding, say an md5 hash, but is distributed under a BSD license in source form. The second is a “Managed” tier, which requires a subscription—accordingly, the company can’t reveal the source code, and in fact doesn’t even give out binary, but a pair of locked-down boxes that users are expected to route sensitive network traffic through, which then manages the traffic in negotiation with their server. The company knows that this routing is completely, 100% secure, say even to the point of mathematical correctness proofs of their hardware and software implementations—but doesn’t transmit that knowledge to its users, on account of their needing to charge for it.

The question is: shouldn’t the user be skeptical of the company’s claims? Maybe the company is the US National Security Agency, or a nationalized Chinese conglomerate, where there’s reason to doubt that the claims’ veracity would be in the company’s interest that may outweigh the objective insecurity of the alternative. If the user has no way to verify the lack of exploitable flaws, shouldn’t he behave as if those flaws existed?

In turn, isn’t this concept of security somewhat irrelevant, if it can have no impact on how users behave? Shouldn’t security be the warrant for trust?

Epistemic Security

In light of these analyses, it would seem that a statement that something is “secure” is a claim to have specific, objectively-evaluatable knowledge that the behavior of an entity aligns with expectations. “Specific” rules out consequential security, whose ultimate flaw was the admission of knowledge too-general; “knowledge” rules out ontological security, which refuses to admit any consideration of the perciever in the determination.

The nature of this knowledge is subject to the same grading and methodological concerns common to all other knowledge: that deduction ought to be preferred unless uncertainty is absolutely necessary (which usually is a situation arising at the very foundation and the very fringe of any discipline), and that formalization ought to be utilized to the greatest extent that practical concerns can possibly admit.

Three Definitions of “Free”

The obvious consequence of epistemic security is that things ought be Free—any information about an entity provided in a representation less informative and more confusing that that which its designers chose to represent it in is being obfuscated, and made deliberately harder for its security to be established. But in what sense is that “F” capitalized; what is the precise, legal, licensing definition of “Free” that best enables security?

Free As In Beer

This is the naive definiton of “free,” completely unrelated to the determination of security, as it concerns only what was sacrificed to obtain the specific entity in question, and nothing about information provided on that entity’s behavior except inasmuch as the provison of that information requires more sacrifice on behalf of the producer than otherwise. However, it is certainly the case in many cases, notably software and other cases where the information and the product are essentially inseparable, that charging any price is senseless without also obfuscating information about the entity’s behavior. It is such cases analyzed below.

Free*

This is the category of entities on which complete information is provided, but with extensive legal stipulations as to exactly what behavior is not permitted, usually eliminating copying, redistributing, modifying, selling, leaking, and other such things. This category of software can be secure, but if it is found to be insecure, its users are completely prevented (in the limit where laws are followed) from doing anything about the change. In the worst case, where relaying the information provided by any means, even to other licensed users, is prohibited, they are prevented from even distributing knowledge of the insecurity!

Free As In Speech

This category is inherently more secure, in the epistemic sense, than anything else. It contains those entities which are distributed with all information that their designer or constructor has in regards to its behavior, and on which no information-destructive restrictions are set on copying, modification, resdistribution or resale, testing, or almost anything else. Only this category of thing has any likelihood of being called secure, as it’s the only condition under which the process of demonstrating and improving security can occur, and have the result be verifiable by its users.

The Problem of Copyleft

One of the blemishes, prima faciae, in common realization of free software licenses in particular are viral or copyleft conditions in open source software licenses, which require that all derived works be at least as freely licensed as that on which it’s based (see e.g. the GPL). This would seem to be contradictory to the idea of “freedom;” it can be best seen as a practical measure on behalf of the FSF to ensure that their efforts never go towards projects running directly counter to their political objectives. However, for the purposes of security, since its only purpose is to prevent obfuscation of external software, it is materially irrelevant.

Utility

By contrast, evaluating how useful something is much less complicated: does it serve its necessary functions better than any alternatives? There are a few general principles that this config attempts to follow, though, employing much of the reasoning above.

  • More secure, more useful: things which behave unpredictably can’t be guaranteed to serve those purposes by definition.
  • Nonfree things can never be secure, and so are always less useful.
  • More minimal, easier to secure: things which serve more functions with less abstraction are more useful, all else equal, as it’s easier to verify that they conform to that abstraction.
  • More mathematically sophisticated abstractions are usually more minimal: mathematics is the study of abstraction, and so has provided some of the most widely applicable abstractions, such as mathematical proofs, categories, and the theory of regular languages and automata. This needs to be balanced against the need for smoothly bootstrapped abstractions (implementing GHC in bare asm and then an OS in that will probably not be the best for total understandability).
  • Experienced users should be unhampered by UI elements that serve to “help” the novice the first time he boots up the program.
  • Extensive, accessible documentation (including documentation-for-documentation) ameliorates the lack of the above.
  • User-extensibility is paramount: no danger of making bad decisions when the user can design their own interface in a couple minutes.
  • More to come, probably.

A Partial Implementation

The rest of this document details what I think is roughly the optimal implementation of these principles, when restricted to selecting from off-the-shelf software available in the early ’20s. Some of the defects of this system I will try to improve, but this system is certainly necessary to bootstrap out those improvements.

Instructions synthesized from Installing Parabola on Libreboot with full disk encryption (including /boot) - ParabolaWiki Luke Smith’s Walkthrough, GnuPG/AirgappedMasterKey - Debian Wikiand Libreboot – Encrypted Guix GNU+Linux, along with the usual suspects: ArchWiki, Gentoo Wiki, man and info.

Hardware Selection

Computer

Purchase a Lenovo Thinkpad X60/T60/T61 secondhand immediately.

These are the unicorn of laptops: excellent physical design, diverse port selection, upgradability and configurability second-to-none, and cheap because they’re “old.” Moreover, they’re some of the only laptops to have FOSS firmware support—this software runs with higher-than-root priveleges, in essence, and is almost invariably closed-source and terrible. Libreboot provides a replacement that’s blob-free. Further, this replacement also disables the Intel Management Engine—an entirely separate operating system, running with higher-than-firmware priveleges; closed-source and with government leaks hinting at backdoors. Libreboot integrates firmware with bootloader, can be password-protected, and can decrypt encrypted volumes. In addition to being free, it is simply the best firmware I have ever used. And that makes the T60 all the more valuable.

You will need an ath9k- or other-libre-driver-compatible wifi card to replace the one included, most likely. Beyond that, consider upgrading the drive to an SSD, maxing out x86’s 2^32 = 4294967296 bytes of RAM, and occupying the PCMCIA card slot with a smart-card reader or a Bluetooth antenna.

Peripherals

A mouse is not needed.

The UltraBase for the T60 is an excellent investment, as it enables the press-button-and-walk-away experience for using external monitors and keyboards with the T60 (also highly recommended).

Extreme care should go into selecting a keyboard, as it will be the primary interface to the system, and can be a source of injury very easily. Pay attention to people who hand-build their own “custom ergo” designs; they have thought quite a lot about what works and why. Consider especially the adjectives split, ortholinear, tented, and mechanical.

Additional Hardware

You will need three reasonably-sized USB drives. 32Gb will do: one to load the OS onto the T60 and serve as a OTP hardware 2fa, and for other general use; one for a Kali airgapped master key to live on; and another for the revocation certificate for said key. These last two uses are extremely schizoid, top-tier-security type applications, and so do indeed need to be separate drives. Consider how much you trust the hardware, and the risk/consequence ratio of trusting one company or model for all three or a different company for each.

You will also likely want an additional device runing a internet-connected Linux GUI, to read documentation and flash the install media. If you don’t have this, it’s still possible to do everything using just the T60, but note down a few things on paper while in the T60’s graphical environment for later use: the Libreboot mirror URL and the GPG signature of the file you’re supposed to download, TODO other stuff.

Preliminaries

On a separate computer, or with the Windows XP the T60 probably came with, go to the corresponding Arch Linux 32 page and download an i686-only ISO and its associated files from a mirror (or as a torrent, if you’re BASED). This ISO will have proprietary drivers etc. on it, but Parabola’s ISOs don’t seem to work with Libreboot or i686 or something. Compare the PGP signature of this ISO against those listed on the official page, and make sure they match:

TODO: verifying

Flash this ISO verbatim onto the disk drive, either using a program like Rufus or efibootmgr if on Windows, or, if on Linux, via

$ sudo dd if=/path/to/ISO of=/path/to/USB/block/device bs=4M; sync

Restart and load this USB drive via the proprietary Lenovo BIOS.

Installing Libreboot

Once in the Arch live environment (do loadkeys emacs to get sensible defaults, e.g. control on capslock, M-p for previous prompt), use a separate computer to navigate the Libreboot – Downloads page, and find an https mirror you like. Navigate to stable/20160907 folder, and note the current page URL. The files you’ll need are the util archive and the file in rom/grub corresponding to the T60 (NB: there’s a different one for the X60). Download them in the live environment with

$ wget https://url/to/libreboot_r20160907_util.tar.xz
$ wget https://url/to/libreboot_r20160907_grub_t60.tar.xz

Also download the SHA512SUMS etc. and verify the contents of everything downloaded. TODO: verifying

Extract these archives’ contents, with

$ tar -xf libreboot_r20160907_util.tar.xz
$ tar -xf libreboot_r20160907_grub_t60.tar.xz

In the grub_t60 folder, there will be a number of files with keyboard layouts and vesafb or txtmode in their names. Copy the one corresponding to your preferred layout which has vesafb (simply a prettier version of GRUB) to the util folder, and chase after it:

$ cp name/of/layout_vesafb.rom ../libreboot_r20160907_util
$ cd ../libreboot_r20160907_utli

Now to the scary stuff. Libreboot should do all the hard work, and everything should be fine, but problems here (and, by extension, before this point) can render the T60 unbootable and requrie an external re-flashing tool to recover. The following flashes the basic configuration to the ROM (this’ll be modified later):

$ ./flash i945lenovo\_firstflash name/of/layout_vesafb.rom

This will give terrifying error messages. If it says “DO NOT REBOOT OR POWEROFF,” you’ve won; type shutdown now (not reboot, apparently) and turn the system back on after it shuts down.

A GRUB-style menu with a GNU background should pop up for a brief moment. By default, it’ll try to boot the main disk drive; use the arrow keys to stop it (if you miss, just power cycle it again). Try typing either s (which searches for GRUB configs on external media) or u (which searches for ISOLINUX configs on external media); one of these should take you back to the ISO’s boot menu. Navigate through this, and go back to the folder we logged off from to continue (preserve sanity with loadkeys emacs if you did so before).

Libreboot needs to run a second flash:

$ ./flash i945lenovo\_secondflash name/of/layout_vesafb.rom

This should run faster and with fewer scary errors. After it finishes successfully, continue installing with the now-spyware-free (or, at least, more-spyware-free) firmware and CPU.

Installing Arch with Full-Disk Encryption

We’ll perform a fairly standard Arch install, before updating Libreboot and migrating to Parabola.

Shred the Past

First, we wipe the disk. Figure out which one it is with

$ lsblk

Needless to say, everything below this point destroys the contents of the T60’s disk drive (or whatever else you mistakenly target with the commands). Take extra care. The drive you’re looking for should be something like /dev/sdX (which the USB will also look like—be extra sure it’s the disk and not the drive!). Wipe the MBR with zeros first (TODO: not sure why this needs to be done separately):

$ dd if=/dev/zero of=/dev/sdX bs=446 count=1; sync

Now, use the kernel’s pseudorandom number generator (use /dev/random/ if you value a tiny increase in security over the multiple extra hours it’ll probably take) to wipe the contents of the drive:

$ dd if=/dev/urandom of=/dev/sdX bs=4M; sync

Connect to the Network

Try

$ ping gnu.org

If they respond, you’re already connected, probably because you chose to plug in a wired connection. Otherwise, if you’re on wired run systemctl restart dhcpcd; if wireless, wifi-menu. Try pinging again; if it still doesn’t work, find other documentation; failing that, hit IRC or the forums.

Setting Up Full-Disk Encryption

Ensure the kernel has the module for encryption:

$ modprobe dm-mod

Set up a single, monolithic partition on the HDD:

# Select 'o' to create a new DOS partition; choose the defaults for everything.
# The result should be a partiton of type '(83) Linux' filling the whole drive.
# No need to set it bootable.
fdisk /dev/sdX

Read a lot about how cryptography and LUKS work. Or, if you’re lazy, run the following command no-questions-asked, which could be one of the completely-insecure and trivial-to-bypass LUKS parameter combinations because I’m evil 😈

$ cryptsetup -v --cipher serpent-xts-plain64 --key-size 512 --hash whirlpool --use-random --verify-passphrase \
  luksFormat --type luks1 /dev/sdX1

Choose a good password. My advice is to use

$ cat /dev/random | tr -cd '[:graph:]' | head -c12

to generate a truly random, 12-character-with-symbols, hyper-secure one. In the end, you’ll only have to remember two of these due to the bomber password manager configuration to be set up; writing them down for now is completely fine (as long as you incinerate, or carry on your person at all times, later).

All of the usual partitions will be LVM volumes inside this encrypted one (which enables all kinds of efficiency). Set the basics of this up:

$ cryptsetup luksOpen /dev/sdX1 lvm       # unlock what we just encrypted
$ pvcreate /dev/mapper/lvm                # make it an LVM physical volume
$ pvdisplay                               # confirm it worked
$ vgcreate matrix /dev/mapper/lvm         # make a volume group on it to contain all our usual partitions
$ vgdisplay                               # confirm again
$ lvcreate -L 4G matrix -n swapvol        # swap partition
$ lvcreate -l +100%FREE matrix -n rootvol # the rest is the root partition

Add any more you want (why tho), and confirm with lvdisplay.

Put the new space to work (choose a different root filesystem if you want):

$ mkswap /dev/mapper/matrix-swapvol     # make swap a swap
$ swapon /dev/matrix/swapvol            # make swap do swaping
$ mkfs.btrfs /dev/mapper/matrix-rootvol # make root a filesystem
$ mount /dev/matrix/rootvol /mnt        # make that filesystem accessible

Setting Up the New Filesystem

Create basic directories in the new root filesystem:

$ mkdir -p /mnt/home
$ mkdir -p /mnt/boot

Now, verify the signatures of the packages:

$ sudo pacman --needed -Syy archlinux-keyring archlinux32-keyring

See the Parabola installation guide for how to deal with errors here.

Now, put any essential packages on the system (feel free to modify the end of this list):

$ pacstrap -K /mnt base linux linux-firmware lvm2 flashrom man-db man-pages texinfo wpa_supplicant dhcpcd emacs xorg-server

An fstab can now be generated, so the filesystem actually works:

$ genfstab -U /mnt >> /mnt/etc/fstab

Copy the Libreboot files from the install medium onto the filesystem (we’ll need the tools to flash an improved Libreboot GRUB config):

$ cp -r libreboot_r20160907_util /mnt/root/

Now, to chroot into the actual system, and finalize things.

Configuring the New System

Chroot into the new system, set the time zone, hardware clock, and your locale:

$ arch-chroot /mnt
$ ln -sf /usr/share/zoneinfo/America/Chicago /etc/localtime # modify if not on God's time
$ hwclock --systohc

Edit /etc/locale.gen to enable any desired locales (en_US.UTF-8 and UTF-8 are good choices).

Generate them with

$ locale-gen

Set LANG=en_US.UTF-8 in /etc/locale.conf, and make Emacs keys in the console persistent by entering KEYMAP=emacs in /etc/vconsole.conf. Create a hostname in /etc/hostname (any file contents will be the hostname; I like using ancient Greek philosophical concepts).

Modify /etc/mkinitcpio.conf to contain the following:

...
MODULES=(i915)
...
FILES=(/etc/keyfile)
...
HOOKS=(base udev autodetect modconf block keyboard keymap consolefont encrypt lvm2 filesystems fsck shutdown)
...

The keyfile will be set up later as a way to pass the system encryption key to the kernel; try to touch it if it causes problems by not existing. There may be room for improvement with the hook, esp. their order, as I simply found one that worked and rolled with it.

Create the initial RAM disk with mkinitcpio -p linux.

Set a root password (remember how we generated the LUKS password above? Do that again—don’t reuse passwords):

$ passwd

One needs not install a bootloader; Libreboot’s GRUB can do all that for us.

Now, we can simply release everything and reboot:

$ exit # from chroot
$ umount -R /mnt
$ swapoff -a
$ lvchange -an /dev/matrix/rootvol
$ lvchange -an /dev/matrix/swapvol
# any others...
$ cryptsetup luksClose lvm
$ poweroff

Getting Into the New System

Remove the USB stick, and power the system back on. Libreboot’s GRUB will need some help booting the system, as we haven’t configured it yet. In the boot menu, press ‘c’ to access the GRUB commandline (which has basic bash-like tab completion), and boot things manually:

grub> cryptomount -a
grub> set root='lvm/matrix-rootvol'
grub> linux /boot/vmlinuz-linux root=/dev/matrix/rootvol cryptdevice=/dev/sda1:root
grub> initrd /boot/initramfs-linux.img
grub> boot

A Quick pacman -Suu your-freedom

After Arch boots, you should be able to login as root using the password you configured. Upgrade the system with pacman -Syu. Disable signature verification temporarily by editing /etc/pacman.conf:

...
SigLevel = Never
...

Install the Parabola keys and mirrors:

# i686 may need to be altered to x86_64; I can't recall.
$ pacman -U https://www.parabola.nu/packages/libre/i686/parabola-keyring/download
$ pacman -U https://www.parabola.nu/packages/libre/i686/pacman-mirrorlist/download

Switch to the new mirrors:

$ cp -vr /etc/pacman.d/mirrorlist.pacnew /etc/pacman.d/mirrorlist

In /etc/pacman.conf, enable the new repositories above the existing Arch ones (order critical):

...
[nonprism]
Include = /etc/pacman.d/mirrorlist
[kernels]
Include = /etc/pacman.d/mirrorlist
[libre]
Include = /etc/pacman.d/mirrorlist
...

Refresh everything:

$ pacman -Scc
$ pacman -Syy
$ pacman-key --refresh
$ pacman -Suu your-freedom pacman your-privacy

Run mkinitcpio -p linux-libre to re-generate the initramfs with the correct kernel. The system should now be fully free; we need only configure Libreboot to boot into the new kernel.

Configuring Libreboot

Creating a Keyfile

We may use a minimal-access file on the encrypted root filesystem, in which the kernel runs after the bootloader unlocks it, to give the kernel an encryption key. However, we first must generate and authorize the keyfile.

$ dd bs=512 count=4 if=/dev/urandom of=/etc/keyfile iflag=fullblock; sync
$ cryptsetup luksAddKey /dev/sdX /etc/keyfile
$ chmod 000 /etc/keyfile

This should already be in the /etc/mkinitcpio.conf made above, but if it isn’t, add it and regenerate the mkinitcpio. The following produces a GRUB config for LIbreboot that, among other things, instructs the kernel to use this keyfile to manipulate the filesystem.

A New Config

The Libreboot utils folder was copied into the /root directory (right?) and we installed the flashrom tool with pacstrap (right?), so we can change to a directory with the tool we need, and dump the ROM contents, inspecting what we get

$ cd /root/libreboot_r20160907_util/cbfstool/i686
$ flashrom -p internal -r dump.rom
$ ./cbfstool dump.rom print

Flashrom may complain about there being multiple chips. I believe I chose the shortest option (appending its name with -c), and it worked out fine. If you see grub.cfg and grubtest.cfg, it’s worked. These two files exist to help avoid rendering the system unbootable, when doing changes like we’re about to. Extract the test config:

$ ./cbfstool dump.rom extract -n grubtest.cfg -f grubtest.cfg

Briefly install grub, to hash a password for us (remember how we generated the LUKS password above? Do that again—don’t reuse passwords), and then leave:

$ pacman -S grub
$ grub-mkpasswd-pbkdf2 # save this output
$ pacman -R grub

Setting a password like this is, strictly speaking, optional, but without it anyone with physical access to the machine could re-flash the boot ROM by loading a Linux kernel they control from the GRUB commandline or an external USB, load a progam that exfiltrates all the contents of RAM (including the passwords you type) over the network to him. Physical access to the machine is, indeed, always insecure against this (DMA protocols for PCI, FireWire, and SPI give an attacker full control of the contents of RAM), but at least those require persistent modification to the computer’s hardware, which is much more noticable than modifying software one hardly thinks about.

Now, edit the contents of the “Load Operating System” function grubtest.cfg as follows, double-checking (perhaps with a reboot) that (ahci0,msdos1) is indeed what your encrypted partition is (avoids any possible attack by manipulating the cryptomount -a order):

...
set superusers="root"
password_pbkdf2 root <your-hash-here>

menuentry 'Parabola Linux-Libre (LVM under full-disk LUKS)  [o]' --hotkey='o' --unrestricted {
    cryptomount (ahci0,msdos1)
    set root='lvm/matrix-rootvol'
    linux /boot/vmlinuz-linux-libre root=/dev/matrix/rootvol cryptdevice=/dev/sda1:root rw cryptkey=rootfs:/etc/keyfile iomem=relaxed
    initrd /boot/initramfs-linux-libre.img
}
menuentry 'Search ISOLINUX menu (AHCI)  [a]' --hotkey='a' --users ""{
    search_isolinux ahci
}
menuentry 'Search ISOLINUX menu (USB)  [u]' --hotkey='u' --users "" {
    search_isolinux usb
}
menuentry 'Search ISOLINUX menu (CD/DVD)  [d]' --hotkey='d' --users "" {
    insmod ata
    for dev in ata0 ata1 ata2 ata3 ahci1; do
        try_isolinux_config "(${dev})"
    done
}
menuentry 'Load test configuration (grub.cfg) inside of CBFS  [t]' --hotkey='t' --unrestricted {
    set root='(cbfsdisk)'
    configfile /grub.cfg
}
menuentry 'Search for GRUB2 configuration on external media  [s]' --hotkey='s' --users "" {
    search_grub usb
}
menuentry 'Poweroff  [p]' --hotkey='p' --unrestricted {
    halt
}
menuentry 'Reboot  [r]' --hotkey='r' --unrestricted {
    reboot
}
...

This will require a GRUB password (with user login “root”) for doing anything in GRUB other than booting Parabola (which requires a LUKS password, and ultimately a user password) or cycling the power.

Flashing and Testing

Save the modifications, and then update the grubtest.cfg file in the ROM (note TEST!!!!!!!! system can brick otherwise) with them:

$ ./cbfstool dump.rom remove -n grubtest.cfg
$ ./cbfstool dump.rom add -n grubtest.cfg -f grubtest.cfg -t raw

Now, change to the libreboot_util directory and run

$ ./ flash update dump.rom

Now, you should be able to reboot and try out the new config. Are passwords required where they should be? Have you written down/remembered them correctly? Do the non-password options work? If so, boot into the system and verify that works. If anything breaks, a simple “t” will return to the original config, which worked to get you this far. If everything works, repeat the flashing steps above, copying the contents of grubtest.cfg to grub.cfg, and modifying the “test configuration” entry to point to grubtest.cfg instead of grub.cfg. Load and flash it the same way as above, reboot, and verify it works (boot via grubtest.cfg or the command line if it doesn’t).

After this reboot, you should have a reasonably-secure-against-physical-access, fully-free, Parabola GNU/Linux-libre system!

Configuring the New System

Adding Users

Doing everything as root is hopelessly dangerous. Add a user:

$ useradd -m -G wheel audio video netdev <other groups> -s <login_shell> <username>

Create a password (using the same guidelines as above—don’t reuse passwords!):

$ passwd <username>

The “wheel” group are all those users permitted to sudo to root; we need to set this up by editing /etc/sudoers using visudo (!!! RISK OF BRICK OTHERWISE): add the line

%wheel    ALL=(ALL:ALL) ALL

Check sudo works with sudo echo BRUH

PAM USB

Note: I’ve since stopped using pam_usb, due to an update’s breaking of the agent resulting in the system becoming unbootable…I configure a keybind to lock all sessions instead.

For 2FA reasons, I like the AUR package pam_usb, which provides a daemon and a PAM module for conditioning authentication of various kinds on a USB being plugged in. This means that anyone looking to authenticate to any account on my computer requires: 1) the knowledge I keep in my head/secured with pass and an airgapped master GPG key, and 2) a device I keep on my person at all times. If the device is lost, the bootloader password (and also the LUKS password) can be used to load Linux manually with init=/bin/sh, and then the PAM files modified—if these passwords are compromised, it likely means the adversary has my GPG decryption key, which means I have bigger problems; top-of-mind should be issuing the revocation certificate, generating a new airgapped master, transerring all my pass files over to the new key, and changing as many of those passwords and coin wallets as I can that the adversary hasn’t done before me. At the very least, it provides an excellent way to trigger locking of the desktop and any open tty sessions when I’m not at the keyboard. Install it (manually, please; AUR package managers are a terrible idea). Ensure you’re using the mcdope fork; at the time of writing, it’s the one to which the pam_usb package points, but that could change.

The USB used to install Arch is no longer needed, so we’ll configure a partition on it to store the one-time pads. The rest can be LUKS-encrypted and used for general file transfer, or to test out other distros (I have one partition for each). Wipe it first if you want, using the same commands above used to wipe the HDD.

$ lsblk # get USB block device --- /dev/sdY
$ dd if=/dev/urandom of=/dev/sdY bs=4M; sync # optional
$ fdisk /dev/sdY # create at least one partition---1G is working great for me so far.
$ mkfs.ext4 /dev/sdY1 # doesn't work with additional encryption; probably is just more inconvenient

The pam_usb tools should now be able to pick up the USB.

$ pamsub-conf --add-device <device_name> # Select /dev/sdY1, and say "yes" to save the config.
$ pamusb-conf --add-user <username>      # Say "yes" to save the config.
$ pamusb-check <username>                # Makes sure it is set up correctly.

Now, to actually require pamusb-check to log in (note: as we haven’t configured pamusb for the root user, this disables root login on tty, but not su), edit /etc/pam.d./system-auth to contain

#%PAM-1.0

auth       required                    pam_faillock.so      preauth
# Optionally use requisite above if you do not want to prompt for the password
# on locked accounts.
-auth      [success=2 default=ignore]  pam_systemd_home.so
auth       required        	    pam_usb.so  # add this line; only change
auth       [success=1 default=bad]     pam_unix.so          try_first_pass nullok
auth       [default=die]               pam_faillock.so      authfail
auth       optional                    pam_permit.so
auth       required                    pam_env.so
auth       required                    pam_faillock.so      authsucc
# If you drop the above call to pam_faillock.so the lock will be done also
# on non-consecutive authentication failures.

-account   [success=1 default=ignore]  pam_systemd_home.so
account    required                    pam_unix.so
account    optional                    pam_permit.so
account    required                    pam_time.so

-password  [success=1 default=ignore]  pam_systemd_home.so
password   required                    pam_unix.so          try_first_pass nullok shadow sha512
password   optional                    pam_permit.so

-session   optional                    pam_systemd_home.so
session    required                    pam_limits.so
session    required                    pam_unix.so
session    optional                    pam_permit.so

I also like changing the required in the first line to requisite, as noted in the comments. In the line added for pam_usb, you can change required to sufficent to make the USB a substitute for a password, but I do not recommend it. NB: you should read the pam.d manpages to understand the signifigance of these changes, and exactly how this file works. The order of things is extremely important.

Now, pam_usb will kick in on any tty login, on sudo authentication, and a few other places that use system-auth. We can configure and enable pamusb-agent to perform actions on connection and disconnection. I like telling it to use xsecurelock to lock the X display, and lock all TTY sessions with vlock:

<!-- User settings -->
<users>

  <!-- ... -->

  <user id="dnw">
    <device>secrets-userauth</device>
    <agent event="lock">
      <env>XSECURELOCK_AUTHPROTO=authproto_pam</env>
      <env>XSECURELOCK_PAM_SERVICE=system-auth</env>
      <env>XSECURELOCK_PASSWORD_PROMPT=time_hex</env>
      <env>DISPLAY=:0.0</env> <!-- Possibly flaky. -->
      <env>XAUTHORITY=/home/dnw/.Xauthority</env>
      <cmd>xsecurelock</cmd>
      <cmd>vlock -a</cmd>
    </agent>
</user></users>

<!-- ... -->

An Airgapped Master Key

An OpenPGP key is usually a frighteningly powerful thing. I personally use mine to encrypt all of my other secrets (including important financial assets and API keys) with pass, to prove I’m me to the world at-large, and communicate securely with people I know over unsecure networks. As such, it pays to be a little schizo. One of the problems with standard key arangements is that if an adversary compromises the main key, he can use that main key generate a revocation certificate, new subkeys signed by the previous key, issue that revocation certificate to nullify all prior arrangements, and carry on impersonating you with new keys, over which you have no control.

An airgapped master key setup minimizes the risk of this happening by separating the powers of day-to-day encryption and decription from those of signing, revocation certificate creation, and subkey generation. If an adversary compromizes the former (much more likely, as they’re used over a wider range of hardware and in much more bloated software environments), he can only encrypt and decrypt things with them; only you have the ability to generate new signed subkeys, issue a revocation certificate, and update your identity to something outside the adversary’s control. The “master key” with such powers is stored exclusively on a leave-no-trace LiveUSB distro like Tails or Kali, and is only ever booted on computers physically disconnected from the Internet (since you now have a T60, via a Kali 32-bit LiveUSB with encrypted persistence, with the T60’s physical WiFi kill switch always off, i.e. no green showing).

Ok, let’s set it all up. Download and verify the Kali 32-bit LiveUSB ISO. Plug in a (different!) USB, figure out which it is with lsblk (say, /dev/sdZ), load the image on the drive, add and encrypt an additional partition, and create a labeled filesystem on it:

$ dd if=/path/to/kali.iso of=/dev/sdZ bs=4M conv=fsync status=progress; sync
$ fdisk /dev/sdZ # Create a new primary partition filling the rest of the drive, and write.
$ cryptsetup luksFormat /dev/sdZ3 # generate a good, new password!
$ cryptsetup luksOpen /dev/sdZ3 airgap
$ mkfs.ext4 -L persistence /dev/mapper/airgap
$ e2label /dev/mapper/airgap persistence

Now, do some Kali nonsense to make the contents of this partition persistent across boots, and we’re done here:

$ mount /dev/mapper/airgap /mnt
$ echo "/ union" | sudo tee /mnt/persistence.conf
$ umount /dev/mapper/airgap
$ cryptsetup luksClose /dev/mapper/airgap

Next, shutdown now, hit the WiFi kill switch (and make sure any cables and Bluetooth devices are unplugged too, for good measure), press s at the Libreboot screen, enter your Libreboot password, and enter Kali. Use your persistence password to unlock the LUKS partition. I’ve had the “Encrypted persistence” GRUB option hang on me before; in that case, just load the normal “Persistence USB” option. It’s not that hard to enter a disk password in Thunar after boot, the downside being you have to copy things into and out of it manually.

Once at the Kali desktop, fiddle around with the awful GUI to open a terminal. Ignore the obnoxious prompt; the pain will pass. Create a new gpg key:

$ gpg --full-gen-key

Select options 4, for a sign-only RSA keypair, a size of 4096, and an expiry from a few months to a couple years. Leave the comment blank; it can cause keysigning problems. Generate a good, distinct passphrase, as always—this (and the Kali LiveUSB LUKS psk) is the critical one; the rest of the passwords can be securely remembered using it. Accordingly, you might want much more entropy; on the other hand, brute-force is very rarely how passwords get leaked, and you will be entering it pretty regularly.

Edit the key, creating subkeys:

$ gpg --expert --edit-key <KEY_ID>
gpg> addkey # option 4
gpg> addkey # option 6
gpg> addkey # option 8 (optional, to make an SSH-compatible key)
gpg> save

These are the main (sub)keys used for day-to-day encryption, in conjunction with the passphrase of the key as a whole.

Insert a third and final USB key, which will hold a revocation certificate for the key. Keep it, preferrably, separate from everything else in a secure location—as it’s a last-resort type thing, possibly used in the case of a forgotten passphrase, it will be kept in unencrypted ext4.

$ lsblk          # Note the revoation cert USB, /dev/sdW.
$ fdisk /dev/sdW # Make one partition, filling the drive.
$ mkfs.ext4 /dev/sdW1
$ mount /dev/sdW1 /mnt
$ gpg --gen-revoke <KEY_ID> > /mnt

Eject this, put it in the bunker vault, and never plug it into a computer again unless you are intending to revoke this master key.

Next, plug in the USB used for the Arch32 ISO. We’ll use this to transfer the subkeys back into Parabola. You might need to format and mount it, as above; consider encrypting it too just to be safe (it wouldn’t be too bad to use your user account password, temporarily—they’ll be residing in the corresponding home directory long-term, anyway).

$ gpg --export <KEY_ID> > /mnt/public.gpg
$ gpgkey2ssh <SUBKEY_ID> > /mnt/ssh.pub # only if you used option 8 above---use the ID of the subkey created there!
$ gpg --export-secret-subkeys <KEY_ID> > /mnt/secret.gpg  # Exports everything /except/ the master.

Make the entire .gnupg directory is saved to the persistence volume! Then, eject everything and reboot into Parabola. Don’t plug the Kali USB into anything unless you intend to sign something, and make sure what you do plug it into is physically airgapped for the entire session. Use USBs to transfer anything in, like we have here.

In Parabola, mount the drive the keys were exported to, and import them to your user’s (not root’s) GPG configuration with

$ gpg --import < /mnt/public.gpg
$ gpg --import < /mnt/secret.gpg

Also copy any SSH auth key to a corresponding location. The last thing we need to do is put ultimate trust in the imported key:

$ gpg --edit-key <KEY_ID>
gpg> trust # set to ultimate, the highest level.

Put the Tails USB in a safe place. It’s probably OK for that to be the same place as the revocation certificate, as losing either one would be equally bad, and keeping hold of just one doesn’t do you much good. Consider writing down the passphrases to the Kali encrypted persistence and the key as well, and storing them alongside (or separate)—this is where careful consideration of your threat model is relevant.

Powertop

There is an occasional whine in the fan on many systems. To defeat this:

Place the following script somewhere on the system, make it read/execute-only, and chown it to root so no user processses can modify it to escalate privilege. This prevents powertop --auto-tune, which will get rid of the whine, from turning off externally connected USB mice and keyboards after annoyingly short inactivity periods.

#!/bin/bash

powertop --auto-tune
HIDDEVICES=$(ls /sys/bus/usb/drivers/usbhid | grep -oE '^[0-9]+-[0-9\.]+' | sort -u)
for i in $HIDDEVICES; do
    echo -n "Enabling " | cat - /sys/bus/usb/devices/$i/product
    echo 'on' > /sys/bus/usb/devices/$i/power/control
done

Edit /etc/systemd/system/powertop.service with the following, to enable powertop:

[Unit]
Description=Powertop tunings

[Service]
Type=oneshot
RemainAfterExit=no
ExecStart=<path-to-script-above>
Environment="TERM=xterm"

[Install]
WantedBy=multi-user.target


Emacs and Userland

See config.org in this repository for my Emacs configuration. It performs most userland functions for me. I do, however, have a .zshrc and .xinitrc that complement that; they’re in this repo as well. Consider especially installing and using pass, the UNIX password manager, with your newly-generated airgapped master key. All your passphrases, or any other file-based secrets, will reside simply in gpg-encrypted files under ~/.password-store, and the executable decrypts them simply and quickly through quite good gpg integration. This directory can be simply synchronized between machines using standard filesharing tools, alongside gpg keys, for simple and secure password management. There are also Android apps that integrate with this; install them from f-droid. Longer-term, consider not using a smartphone.

Try especially to avoid bad websites on the internet. By “bad,” I mean ones that don’t work without executing unnamed, unlicensed JS scripts on your computer. If you absolutely must visit some such, use a browser like Icecat, Iceweasel, or Librewolf. But try to stick to ones browsable with bare HTML.