aboutsummaryrefslogtreecommitdiff
path: root/system.org
blob: 3b832816033d069a9aa8a9f4305f88965fb2a8b1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
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 [[https://wiki.parabola.nu/Installing_Parabola_on_Libreboot_with_full_disk_encryption_(including_/boot)][Installing Parabola on Libreboot with full disk encryption (including /boot) - ParabolaWiki]] [[https://youtube.com/watch?v=1K5jo9gk9LQ][Luke Smith's Walkthrough]], [[https://wiki.debian.org/GnuPG/AirgappedMasterKey][GnuPG/AirgappedMasterKey - Debian Wiki]]and [[https://libreboot.at/docs/gnulinux/guix.html][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 [[https://www.archlinux32.org/download/][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

#+begin_src shell

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

#+end_src

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 [[https://libreboot.org/download.html#https][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

#+begin_src shell

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

#+end_src

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

Extract these archives' contents, with

#+begin_src shell

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

#+end_src

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:

#+begin_src shell

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

#+end_src

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):

#+begin_src shell

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

#+end_src

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:

#+begin_src shell

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

#+end_src

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

#+begin_src shell

  $ lsblk

#+end_src


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):

#+begin_src shell

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

#+end_src

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:

#+begin_src shell

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

#+end_src

*** Connect to the Network

Try

#+begin_src shell

  $ ping gnu.org

#+end_src

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:

#+begin_src shell

  $ modprobe dm-mod

#+end_src

Set up a single, monolithic partition on the HDD:

#+begin_src shell

  # 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

#+end_src

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 😈

#+begin_src shell

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

#+end_src

Choose a good password. My advice is to use

#+begin_src shell

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

#+end_src

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:

#+begin_src shell

  $ 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

#+end_src

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):

#+begin_src shell

  $ 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

#+end_src

*** Setting Up the New Filesystem

Create basic directories in the new root filesystem:

#+begin_src shell

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

#+end_src

Now, verify the signatures of the packages:

#+begin_src shell

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

#+end_src

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):

#+begin_src shell

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

#+end_src

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

#+begin_src shell

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

#+end_src

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

#+begin_src shell

  $ cp -r libreboot_r20160907_util /mnt/root/

#+end_src

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:

#+begin_src shell

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

#+end_src

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

Generate them with

#+begin_src shell

  $ locale-gen

#+end_src

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:

#+begin_src shell

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

#+end_src

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):

#+begin_src shell

  $ passwd

#+end_src

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

Now, we can simply release everything and reboot:

#+begin_src shell

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

#+end_src

*** 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:

#+begin_src shell

  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

#+end_src

** 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=:

#+begin_src shell

  ...
  SigLevel = Never
  ...

#+end_src

Install the Parabola keys and mirrors:

#+begin_src shell

  # 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

#+end_src

Switch to the new mirrors:

#+begin_src shell

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

#+end_src

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

#+begin_src shell
  ...
  [nonprism]
  Include = /etc/pacman.d/mirrorlist
  [kernels]
  Include = /etc/pacman.d/mirrorlist
  [libre]
  Include = /etc/pacman.d/mirrorlist
  ...
#+end_src

Refresh everything:

#+begin_src shell

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

#+end_src

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.

#+begin_src shell

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

#+end_src

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

#+begin_src shell

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

#+end_src

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:

#+begin_src shell

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

#+end_src

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:

#+begin_src shell

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

#+end_src

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):

#+begin_src shell

  ...
  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
  }
  ...

#+end_src

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:

#+begin_src shell

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

#+end_src

Now, change to the =libreboot_util= directory and run

#+begin_src shell

  $ ./ flash update dump.rom

#+end_src

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:

#+begin_src shell

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

#+end_src

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

#+begin_src shell

  $ passwd <username>

#+end_src

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

#+begin_src shell

  %wheel    ALL=(ALL:ALL) ALL

#+end_src

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.

#+begin_src shell

  $ 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

#+end_src

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

#+begin_src shell

  $ 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.

#+end_src

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

#+begin_src shell

  #%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

#+end_src

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=:

#+begin_src nxml

  <!-- 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>

  <!-- ... -->

#+end_src

*** 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 [[https://cdimage.kali.org/kali-2023.2/kali-linux-2023.2-live-i386.iso][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:

#+begin_src shell

  $ 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

#+end_src

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

#+begin_src shell

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

#+end_src

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:

#+begin_src shell

  $ gpg --full-gen-key

#+end_src

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:

#+begin_src shell

  $ 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

#+end_src

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=.

#+begin_src shell

  $ 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

#+end_src

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).

#+begin_src shell

  $ 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.

#+end_src

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

#+begin_src shell

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

#+end_src

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:

#+begin_src shell

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

#+end_src

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.

#+begin_src shell
  #!/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

#+end_src


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

#+begin_src systemd

  [Unit]
  Description=Powertop tunings

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

  [Install]
  WantedBy=multi-user.target


#+end_src

*** 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.