forked from public/airgap
1
0
Fork 0

Compare commits

..

35 Commits

Author SHA1 Message Date
Ryan Heywood 1f26de8fc1
Merge branch '2024.8.1' 2024-08-08 04:20:22 -04:00
Ryan Heywood 4ad5be07db
sign 2024.8.1 2024-08-08 04:18:41 -04:00
Lance Vick 657a3ff611
release: 2024.8.1 2024-08-08 01:13:02 -07:00
Lance Vick ea623cc147
Merge remote-tracking branch 'origin/ryansquared/bump-keyfork-v0.2.3' 2024-08-08 00:34:41 -07:00
Ryan Heywood 95ccf80fe8
Containerfile: bump stagex to include new keyfork version 2024-08-08 01:14:24 -04:00
Ryan Heywood 5904a22c80
add signatures for 2024.8.0 2024-08-04 20:16:21 -04:00
Anton Livaja 485fc58bfb
feat: add sig 2024-08-04 18:15:11 -04:00
Lance Vick e1c677bc06
add signature 2024-08-04 14:19:33 -07:00
Lance Vick dc8515ea02
release: 2024.8.0 2024-08-04 14:17:11 -07:00
Lance Vick 3cb460b72e
GIT_KEY GIT_PUBKEY 2024-08-04 13:29:39 -07:00
Lance Vick f1c0f2f8b5
working reproduction 2024-08-04 13:11:28 -07:00
Lance Vick 1f2ce99275
ignore additional folders 2024-08-04 13:10:24 -07:00
Lance Vick 721ffad1f0
cache/determinism fixes and doc updates 2024-08-03 15:52:30 -07:00
Lance Vick 74bf27bc66
Merge branch 'main' into stagex-rewrite 2024-08-02 22:15:34 -07:00
Lance Vick 44e18ea21b
fix default VERSION arg 2024-08-02 22:05:27 -07:00
Lance Vick a2a3cce64c
fix previous env import on reproduce 2024-08-02 21:58:30 -07:00
Lance Vick f0270a2862
default VERSION to development 2024-08-02 21:44:19 -07:00
Lance Vick 24725ea630
add initial release/reproduction/signing targets 2024-08-02 21:39:15 -07:00
Lance Vick 96ea9054f9
track dist/airgap.iso in lfs 2024-08-02 21:38:46 -07:00
Lance Vick 4676d9f889
hash lock all the things 2024-08-02 18:22:16 -07:00
Lance Vick d1707c48f1
docs: first pass of stagex doc fixes 2024-06-27 00:35:06 -07:00
Lance Vick 51ec4ca719
feat: working sd card automounting with via udev 2024-06-27 00:14:34 -07:00
Lance Vick f735b7e3af
Virtual sd card support 2024-06-26 00:46:56 -07:00
Lance Vick c20dedcc35
pcscd, udevd, and yubikeys working at boot 2024-06-20 20:42:57 -07:00
Lance Vick d737fce6ea
Working EFI/Bios Stagex boot 2024-06-18 01:45:21 -07:00
Lance Vick e886bc51fa
working vm-bios and vm-efi targets 2024-06-17 11:56:18 -07:00
Lance Vick fbdb919b7f
Second pass w/ hybrid grub/syslinux for efi/bios boot 2024-06-11 14:07:13 -07:00
Anton Livaja df223e6deb
fix: typo 2024-03-28 19:55:28 -04:00
Anton Livaja 1578b3c76d
chore: sign 2024.03.13 2024-03-28 18:56:12 -04:00
Anton Livaja 0af9d294a7
chore: clean up build section 2024-03-28 11:38:56 -04:00
Anton Livaja dc60d53fca
fix: typo 2024-03-28 11:28:27 -04:00
Ryan Heywood 16479807f1
sign 2024.03.13 2024-03-13 17:10:07 -04:00
Spencer Judd 38689b24b2
Release 2024.03.13 2024-03-13 14:32:10 -04:00
Lance Vick de0a962876
Merge remote-tracking branch 'origin/refs/pull/2/head' 2024-03-09 22:12:58 -08:00
Spencer Judd 7d9f87c976
Enable kernel webcam support
These four kernel config changes are sufficient to get the webcam
working on the Librem 14.
2024-03-09 22:55:26 -05:00
27 changed files with 795 additions and 112 deletions

1
.gitattributes vendored
View File

@ -1 +1,2 @@
dist/*.iso filter=lfs diff=lfs merge=lfs -text
dist/airgap.iso filter=lfs diff=lfs merge=lfs -text

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
cache/
out/
out*/
.*

View File

@ -1,69 +1,193 @@
FROM stagex/busybox AS busybox
FROM stagex/musl AS musl
FROM stagex/xorriso AS xorriso
FROM stagex/syslinux AS syslinux
FROM stagex/cpio AS cpio
FROM stagex/linux-airgap AS linux
FROM stagex/mtools AS mtools
FROM stagex/dosfstools AS dosfstools
FROM stagex/busybox:sx2024.08.1@sha256:8cb9360041cd17e8df33c5cbc6c223875045c0c249254367ed7e0eb445720757 AS busybox
FROM stagex/musl:sx2024.08.1@sha256:f888fcf45fabaaae3d0268bcec902ceb94edba7bf8d09ef6966ebb20e00b7127 AS musl
FROM stagex/xorriso:sx2024.08.1@sha256:9ab45852aee077b68ea101173025be6e1cdbde93692efa4ee198e1960f02ab52 AS xorriso
FROM stagex/syslinux:sx2024.08.1@sha256:909dcabcf13bd39b0138309f6efdeb780e01c00bf17cb1e7ee851e8b8be74d2b AS syslinux
FROM stagex/cpio:sx2024.08.1@sha256:25afad810fbb9b1d02762030c3e43e07259a79627dbea9b66ef7f797f8377a2a AS cpio
FROM stagex/linux-airgap:sx2024.08.1@sha256:a4fac3ca7795e171a4d1b3b634fdae1790d4f8d076f3c1ac8a38f3ece72e1ec5 AS linux-airgap
FROM stagex/mtools:sx2024.08.1@sha256:b6202dc29906ea8d7594bce604cb676f5335cc51e75e3f12b5f619e8fc27cc28 AS mtools
FROM stagex/xz:sx2024.08.1@sha256:f6ca72fc9096ef5f694b6b7f9b7ad323a571d9447eb5cc790042f72e69b9aad8 AS xz
FROM stagex/eudev:sx2024.08.1@sha256:66020d28246af1d1e5f8fe3b5bca3da3cbfbd1f89cc1c616b7f8d13f61419026 AS eudev
FROM stagex/ccid:sx2024.08.1@sha256:0f50ff4441d8b20ff73babab652fc0a563bce46385100240de4ae587012c9505 AS ccid
FROM stagex/libusb:sx2024.08.1@sha256:c67807377fb18d2a874d975b43e37056eb4067a5be74ebf8c1f5e5ec65ae5650 AS libusb
FROM stagex/keyfork:sx2024.08.1@sha256:bd6167d2a4a6c3b1c3f9c0accbb1fe0d5854f64997bd1d9d8d822cdf628f8baf AS keyfork
FROM stagex/openpgp-card-tools:sx2024.08.1@sha256:088dbc336e34f16f7a8e323f114918468a7e4b13b190c43593ca7b0dffea54b4 AS openpgp-card-tools
FROM stagex/gpg:sx2024.08.1@sha256:b5b0726171f66da437dbd24d2398cd324b96f00115770767b4f72df2547c5323 AS gpg
FROM stagex/bash:sx2024.08.1@sha256:395e85b2f017c3fd30810d12eea5d59b015f6f5387f79bdec808ca01408cfe86 AS bash
FROM stagex/grub:sx2024.08.1@sha256:5f382615881470e0cf9c670bead785507545a2b829b391247313f516c63355e3 AS grub
FROM stagex/npth:sx2024.08.1@sha256:7899c399f2924c5ba0dfbce9ce6f8391e27ecd0564f0341fb85f83ba293e1ebe AS npth
FROM stagex/libksba:sx2024.08.1@sha256:a5aac434ffd8fca96c435756fac9e300b3d06e04a15c707d09e5e8a16c0bcd89 AS libksba
FROM stagex/libgpg-error:sx2024.08.1@sha256:e7e4797f38ba1a09ba700c91e2a5c99230f04f31e7961101a72d4e95f653f284 AS libgpg-error
FROM stagex/libassuan:sx2024.08.1@sha256:1267bb842bcb6e8bff56e2b72599357605a5e141f76629f7e96187ae85a07197 AS libassuan
FROM stagex/libgcrypt:sx2024.08.1@sha256:ea1906215d18688d96fc5329301af649834fe96c5eadda74c9d485623efb1f90 AS libgcrypt
FROM stagex/jq:sx2024.08.1@sha256:0297a099ae95eed13d48bce2d4d624544857680095b6201e9919e1d5da45a6cd AS jq
FROM stagex/yq:sx2024.08.1@sha256:10e80bd7cec3c6e0a7fd36c65bac13600368bff993ad42b03e3b787d2125e5f0 AS yq
FROM stagex/bc:sx2024.08.1@sha256:1ecf6029ceed91dd62b08c64e49f00518edcf6c10ac4ab2fe7e8f71943607eef AS bc
FROM stagex/zlib:sx2024.08.1@sha256:d0d6eef463a410191e086448c710441109ae72693cb074fe2b795ee033aa6c9d AS zlib
FROM stagex/tpm2-tools:sx2024.08.1@sha256:1693d4ef7e0b7df3e9bd60088588d94b7f5bf755fde0c1be695f3c2f00ec2897 AS tpm2-tools
FROM stagex/tpm2-tss:sx2024.08.1@sha256:5e362f43a5e0c49f774605a0e3e1b7523dc6bc775f537c206a3aaa8b8b733c93 AS tpm2-tss
FROM stagex/openssl:sx2024.08.1@sha256:9bd55ed05263a538e6a23c0262edc356c998a24674f3b8ad008a4b117a4cdf3b AS openssl
FROM stagex/sops:sx2024.08.1@sha256:7d8d51e41c7cab21b8ae75f557961f20405f727a21107d669080e3804d09665c AS sops
FROM stagex/pcsc-lite:sx2024.08.1@sha256:fd9b0600f7f73f87d9d678b8b8a7119e0f9b9314c9959bd0d180c31736cb97d6 AS pcsc-lite
FROM stagex/pcsc-tools:sx2024.08.1@sha256:d83997bda2b9500c8a4567df827a90d65efa842f9a2bb361b6f394589cf167d5 AS pcsc-tools
FROM stagex/flashtools:sx2024.08.1@sha256:e2ac807475e66201ad50eee09bf9625ad0e97dc136818ff11775cb13a54d764b AS flashtools
FROM stagex/libqrencode:sx2024.08.1@sha256:1927d17aaf1ad6a9910380714f0dd12c72c69f9ee1b19668bf4cc5f89cbc2b2d AS libqrencode
FROM stagex/util-linux:sx2024.08.1@sha256:41525597d1f5648dc2318da7779e3c5194b4e6d24cb07f2f616ac539bb094d04 AS util-linux
FROM stagex/opensc:sx2024.08.1@sha256:8da704d0078d445d3af0338764b9f3a87ba4841744c396c8eddef15466366553 AS opensc
FROM scratch AS base
ARG VERSION development
ARG GIT_TIMESTAMP null
ARG GIT_AUTHOR null
ARG GIT_REF null
ARG GIT_PUBKEY null
COPY --from=busybox . /
COPY --from=musl . /
COPY --from=xorriso . /
COPY --from=cpio . /
COPY --from=mtools . /
COPY --from=linux . /
COPY --from=dosfstools . /
COPY --from=syslinux . /
COPY --from=xz . /
COPY --from=grub . /
FROM base AS build
COPY --from=linux /bzImage /iso/boot/bzImage
COPY --from=stagex/busybox . initramfs
COPY --chmod=0755 <<-EOF initramfs/init
#!/bin/sh
/bin/sh
## Kernel
COPY --from=linux-airgap /bzImage iso/boot/vmlinuz
## Initramfs
COPY --from=busybox . initramfs
COPY --from=eudev . initramfs
COPY --from=musl . initramfs
COPY --from=zlib . initramfs
COPY --from=npth . initramfs
COPY --from=libksba . initramfs
COPY --from=libgpg-error . initramfs
COPY --from=libassuan . initramfs
COPY --from=libgcrypt . initramfs
COPY --from=keyfork . initramfs
COPY --from=bash . initramfs
COPY --from=gpg . initramfs
COPY --from=jq . initramfs
COPY --from=yq . initramfs
COPY --from=bc . initramfs
COPY --from=flashtools . initramfs
COPY --from=tpm2-tools . initramfs
COPY --from=tpm2-tss . initramfs
COPY --from=openssl . initramfs
COPY --from=libusb . initramfs
COPY --from=ccid . initramfs
COPY --from=pcsc-lite . initramfs
COPY --from=pcsc-tools . initramfs
COPY --from=openpgp-card-tools . initramfs
COPY --from=libqrencode . initramfs
COPY --from=opensc . initramfs
COPY --from=util-linux . initramfs
COPY --from=sops . initramfs
COPY rootfs/ initramfs
COPY <<-EOF initramfs/etc/environment
export VERSION="$VERSION"
export GIT_TIMESTAMP="$GIT_TIMESTAMP"
export GIT_AUTHOR="$GIT_AUTHOR"
export GIT_REF="$GIT_REF"
export GIT_PUBKEY="$GIT_PUBKEY"
EOF
RUN cd initramfs && find . | cpio -o -H newc | gzip -9 > /iso/boot/init.gz
COPY <<-EOF iso/isolinux/isolinux.cfg
DEFAULT linux
LABEL linux
KERNEL boot/bzImage
APPEND initrd=boot/init.gz
EOF
COPY --from=syslinux /usr/share/syslinux/isolinux.bin iso/isolinux/
COPY --from=syslinux /usr/share/syslinux/ldlinux.c32 iso/isolinux/
RUN <<-EOF
set -eux
mkdir -p iso/efi
truncate -s $((10796+128+128))k iso/efi/esp.img
mkfs.fat -F 16 -f 1 -M 0xF0 -r 112 -R 1 iso/efi/esp.img
mmd -i iso/efi/esp.img ::boot
mcopy -i iso/efi/esp.img iso/boot/bzImage ::boot/bzImage
mcopy -i iso/efi/esp.img iso/boot/init.gz ::boot/init.gz
mmd -i iso/efi/esp.img ::syslinux
mcopy -i iso/efi/esp.img iso/isolinux/isolinux.cfg ::syslinux/syslinux.cfg
mcopy -i iso/efi/esp.img /usr/share/syslinux/efi64/ldlinux.e64 ::syslinux/ldlinux.e64
mmd -i iso/efi/esp.img ::efi
mmd -i iso/efi/esp.img ::efi/boot
mcopy -i iso/efi/esp.img /usr/share/syslinux/efi64/syslinux.efi ::efi/boot/boot64.efi
ls -Rlah iso
cd initramfs
find . -exec touch -hcd "@0" "{}" +
find . -print0 \
| sort -z \
| cpio \
--null \
--create \
--verbose \
--reproducible \
--format=newc \
| gzip --best \
> ../iso/boot/initramfs
EOF
## Grub (EFI Boot)
COPY config/grub.cfg iso/boot/grub/grub.cfg
COPY config/grub_early.cfg grub_early.cfg
RUN <<-EOF
set -eux
mkdir -p efi/boot
grub-mkimage \
--config="grub_early.cfg" \
--prefix="/boot/grub" \
--output="efi/boot/bootx64.efi" \
--format="x86_64-efi" \
--compression="xz" \
all_video \
disk \
part_gpt \
part_msdos \
linux \
normal \
configfile \
search \
search_label \
efi_gop \
fat \
iso9660 \
gzio \
serial \
terminal
find efi -exec touch -hcd "@0" "{}" +
mformat -i iso/boot/grub/efi.img -C -f 1440 -N 0 ::
mcopy -i iso/boot/grub/efi.img -ms efi ::
touch -md "@0" iso/boot/grub/efi.img
EOF
## Syslinux (BIOS Boot)
COPY config/syslinux.cfg iso/boot/syslinux/
COPY --from=syslinux \
/usr/share/syslinux/isohdpfx.bin \
/usr/share/syslinux/isolinux.bin \
/usr/share/syslinux/ldlinux.c32 \
/usr/share/syslinux/libutil.c32 \
/usr/share/syslinux/libcom32.c32 \
/usr/share/syslinux/mboot.c32 \
iso/boot/syslinux/
## Build Hybrid EFI/BIOS ISO
FROM build AS install
RUN xorriso \
-as mkisofs \
-output airgap.iso \
-eltorito-boot isolinux/isolinux.bin \
-no-emul-boot \
-boot-load-size 4 \
-boot-info-table \
-eltorito-alt-boot \
-eltorito-platform efi \
-eltorito-boot efi/esp.img \
-no-emul-boot \
-eltorito-catalog isolinux/boot.cat \
iso
#RUN isohybrid airgap.iso
ENV SOURCE_DATE_EPOCH=1
# --set_all_file_dates='1'
# --modification-date='1970010100000000' \
RUN <<-EOF
set -eux
find iso -exec touch -hcd "@0" "{}" +
xorrisofs \
-output airgap.iso \
-full-iso9660-filenames \
-joliet \
-rational-rock \
-sysid LINUX \
-volid "airgap" \
-isohybrid-mbr iso/boot/syslinux/isohdpfx.bin \
-eltorito-boot boot/syslinux/isolinux.bin \
-eltorito-catalog boot/syslinux/boot.cat \
-no-emul-boot \
-boot-load-size 4 \
-boot-info-table \
-eltorito-alt-boot \
-e boot/grub/efi.img \
-no-emul-boot \
-isohybrid-gpt-basdat \
-follow-links \
iso/
EOF
## Minimal Autorun SD card image
COPY sdcard sdcard
RUN <<-EOF
set -eux
dd if=/dev/zero of=sdcard.img bs=1M count=32
mformat -v external -i sdcard.img ::
mcopy -i sdcard.img -s sdcard/* ::
EOF
FROM scratch AS package
COPY --from=install /sdcard.img /
COPY --from=install /airgap.iso /

138
Makefile
View File

@ -1,21 +1,131 @@
VERSION := development
GIT_REF := $(shell git log -1 --format=%H)
GIT_AUTHOR := $(shell git log -1 --format=%an)
GIT_PUBKEY := $(shell git log -1 --format=%GP)
GIT_TIMESTAMP := $(shell git log -1 --format=%cd --date=iso)
export
## Use env vars from latest release when reproducing
ifdef REPRODUCE
include dist/release.env
export
endif
ifdef NOCACHE
NO_CACHE := --no-cache
endif
.DEFAULT_GOAL :=
.PHONY: default
default: \
$(OUT_DIR)/airgap.iso
out/release.env \
out/manifest.txt \
out/airgap.iso
.PHONY: vm
vm:
$(call toolchain,$(USER)," \
qemu-system-i386 \
-M pc \
-nographic \
-cdrom "$(OUT_DIR)/airgap.iso"; \
")
## Primary targets
$(OUT_DIR)/airgap.iso: \
$(FETCH_DIR)/buildroot
out/airgap.iso: Containerfile $(shell git ls-files rootfs)
SOURCE_DATE_EPOCH=1 \
docker build \
--progress=plain \
--output type=oci,tar=false,force-compression=true,name=airgap,dest=airgap \
. \
-f Containerfile
--output type=local,rewrite-timestamp=true,dest=out \
--build-arg SOURCE_DATE_EPOCH=1 \
--build-arg VERSION="$(VERSION)" \
--build-arg GIT_REF="$(GIT_REF)" \
--build-arg GIT_AUTHOR="$(GIT_AUTHOR)" \
--build-arg GIT_PUBKEY="$(GIT_PUBKEY)" \
--build-arg GIT_TIMESTAMP="$(GIT_TIMESTAMP)" \
$(NO_CACHE) \
-f Containerfile \
.
## Development Targets
.PHONY: vm
vm: vm-bios
.PHONY: vm-bios
vm-bios: out/airgap.iso
qemu-system-x86_64 \
-m 4G \
-machine pc \
-serial stdio \
-usb \
-device sdhci-pci \
-device sd-card,drive=external \
-usbdevice tablet \
-drive id=external,if=none,format=raw,file=out/sdcard.img \
-display gtk,show-menubar=off,zoom-to-fit=on \
-cdrom "out/airgap.iso"
.PHONY: vm-efi
vm-efi: out/airgap.iso
qemu-system-x86_64 \
-m 4G \
-machine pc \
-serial stdio \
-bios /usr/share/ovmf/OVMF.fd \
-usb \
-device sdhci-pci \
-device sd-card,drive=external \
-usbdevice tablet \
-drive id=external,if=none,format=raw,file=out/sdcard.img \
-display gtk,show-menubar=off,zoom-to-fit=on \
-cdrom "out/airgap.iso"
## Signing, Verification, and Release Targets
.PHONY: clean
clean:
rm -rf out
.PHONY: release
release: clean
rm -rf dist/*
$(MAKE) NOCACHE=1 VERSION=$(VERSION)
cp -R out/release.env out/airgap.iso out/manifest.txt dist/
.PHONY: sign
sign:
set -e; \
git config --get user.signingkey 2>&1 >/dev/null || { \
echo "Error: git user.signingkey is not defined"; \
exit 1; \
}; \
fingerprint=$$(\
git config --get user.signingkey \
| sed 's/.*\([A-Z0-9]\{16\}\).*/\1/g' \
); \
gpg --armor \
--detach-sig \
--output dist/manifest.$${fingerprint}.asc \
dist/manifest.txt
.PHONY: verify
verify: | dist/manifest.txt
set -e; \
for file in dist/manifest.*.asc; do \
echo "\nVerifying: $${file}\n"; \
gpg --verify $${file} dist/manifest.txt; \
done;
.PHONY: reproduce
reproduce: clean | out
$(MAKE) REPRODUCE=true NOCACHE=1
diff -q out/manifest.txt dist/manifest.txt;
out:
mkdir -p $@
out/release.env: $(shell git ls-files) | out
echo 'VERSION=$(VERSION)' > out/release.env
echo 'GIT_REF=$(GIT_REF)' >> out/release.env
echo 'GIT_AUTHOR=$(GIT_AUTHOR)' >> out/release.env
echo 'GIT_PUBKEY=$(GIT_PUBKEY)' >> out/release.env
echo 'GIT_TIMESTAMP=$(GIT_TIMESTAMP)' >> out/release.env
out/manifest.txt: out/airgap.iso out/release.env | out
openssl sha256 -r \
out/airgap.iso \
out/release.env \
| sed -e 's/ \*out\// /g' -e 's/ \.\// /g' \
> $@

View File

@ -1,24 +1,26 @@
# AirgapOS #
<https://github.com/distrust-foundation/airgap>
<https://git.distrust.co/public/airgap>
## About ##
A live buildroot based Liux distribution designed for managing secrets offline.
A full-source-bootstrapped, deterministic, minimal, immutable, and offline,
workstation linux distribution designed for creating and managing secrets
offline.
Built for those of us that want to be -really- sure our most important secrets
are managed in a clean environment with an "air gap" between us and the
internet with high integrity on the supply chain of the firmware and OS used.
## Uses ##
* Generate GPG keychain
* Generate PGP keychain
* Store/Restore gpg keychain to security token such as a Yubikey or Nitrokey
* Signing cryptocurrency transactions
* Generate/backup BIP39 universal cryptocurrency wallet seed
* Store/Restore BIP39 seed to a hardware wallet such as a Trezor or Ledger
## Features ##
* Determinsitic iso generation for multi-party code->binary verification
* Deterministic iso generation for multi-party code->binary verification
* Small footprint (< 100MB)
* Immutable and Diskless: runs from initramfs
* Network support and most drivers removed to minimize exfiltration vectors
@ -27,37 +29,54 @@ internet with high integrity on the supply chain of the firmware and OS used.
### Software ###
* docker 18+
* docker 26+
### Hardware ###
* Recommended: PC running coreboot-heads
* Allows for signed builds, and verification of signed sd card payloads
* Ensure any Wifi/Disk/Bluetooth/Audio devices are disabled/removed
* Supported remote attestation key (Librem Key, Nitrokey, etc)
* Supported GPG smartcard device (Yubikey, Ledger, Trezor, Librem Key, etc)
* x86_64 PC or laptop
* linuxboot/heads firmware supported and recommended for multi-use machine
* Allows for signed builds, and verification of signed sd card payloads
* Ensure any Wifi/Disk/Bluetooth/Audio devices are disabled/removed
* Blank flash drive
* Blank SD card
## Build ##
### Update git submodules
```
git submodule update --init --recursive
```
### Build a new release
```
make release
```
```
make release
```
### Reproduce an existing release
```
make attest
```
```
make attest
```
### Sign an existing release
```
make sign
```
```
make sign
```
## Provisioning ##
1. Write airgap.iso to CD-ROM or SD Card
a. `dd if=out/airgap.iso of=/dev/sda bs=1M conv=sync status=progress`
b. `cdrecord out/airgap.iso`
2. Verify media still produces expected hash
```
sha256sum out/airgap.iso
head -c $(stat -c '%s' airgap.iso) /dev/sda | sha256sum
```
## Setup ##

5
config/grub.cfg Normal file
View File

@ -0,0 +1,5 @@
set timeout=1
menuentry "Linux Airgap" {
linux /boot/vmlinuz init=/init console=ttyS0 console=tty0 ro
initrd /boot/initramfs
}

2
config/grub_early.cfg Normal file
View File

@ -0,0 +1,2 @@
search --no-floppy --set=root --label "airgap"
set prefix=($root)/boot/grub

8
config/syslinux.cfg Normal file
View File

@ -0,0 +1,8 @@
TIMEOUT 2
PROMPT -1
DEFAULT Airgap
LABEL Airgap
MENU LABEL Linux Airgap
KERNEL /boot/vmlinuz
INITRD /boot/initramfs
APPEND init=/init console=ttyS0 console=tty0 ro

BIN
dist/airgap.iso (Stored with Git LFS) vendored Normal file

Binary file not shown.

16
dist/manifest.36C8AAA9.asc vendored Normal file
View File

@ -0,0 +1,16 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEZ1U/vaRrtxq9LgsLjkeh7DWhVR0FAma0fbsACgkQjkeh7DWh
VR0lYBAAsjKcqgoSM73lck4gSga3CWtTfZ/k7azr98HnUw5InTyTwvna2sRGL3jb
Q0pUhrPVQVmjXSyxD/hR/uLuiAfUn2Gyhp1MZS3C7jmFcRsxCJzNbByv/2bUS2+U
5TaCoxmM8SdxTqcBIyYylKzZ4ub0t3bCWUt2uPqdSqslgEReeqbzzE3jpmiUfmHE
daaZhZa3iPEr7vqq00jUGFuSEdxQCQkty0nZHzfGhHwbliiUGyH6/bb+u4v5eGYH
VEyRq0CWFgw5sywpSf3UZjR0fkd0do9z6Li1ggN2GV63I4oT3L1LltcMXtgfMp+B
SA3gz7/mJsMqM6H2ZWqUgJAZw/mZCGStftSnOTKdyEtpzagNNeePa5f4kM1ZuHF6
ehSl1nbnCeCPfedS8+oUm3v8qWiFLXz4tmYvBnfDWaUXIYpNOrvJPtatdinTNRfl
nglyEt6Olc+3vEqkrEl7JFu13Gl92mbuhhelKjM/VDheHBUZ6yrso1aLbyruO+wm
RxL3pQSCNfAnIQpSdkXga5gVvbZDDISBast3qHFuZaZFbo2p24hw0HnLAfyCrxgF
JnN3x2qqRlTzQSrVr4EEXUwUqpt5LlnQ3kDLNVYhXuqTdmyETj1YGnAXkqV/D+Z7
B7hlDdddXI5d0yDoYPAmF9N7XJCasdfutnO/8IfZ/eE989jYybE=
=eruT
-----END PGP SIGNATURE-----

16
dist/manifest.8E401478A3FBEF72.asc vendored Normal file
View File

@ -0,0 +1,16 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEiII6deyqeGsP84sUjkAUeKP773IFAma0f0IACgkQjkAUeKP7
73I33w//SaGbbM9z8SYsWhii1SBnfs6NVQSwdBoO20C4gFdmZkPVDak3QoCAioaC
GjlEOEDb7SXfWi3n2z72P97dswN6dG1IxQKR1N913IWzUUEXGR0phaC+o0P1/f74
MXrcUDLwwJwZsA/0zMV6gHvONEqwgmfEO4WrEB/Ty7ueoJjsmQ2oauWytlh8CVDR
3HFwiVoAjRC2d0vKj0eL2n9pNQNEYKb+oJ/gq3sk2L8qPs1vThQguHADvqmi6V3w
+4tZqviksPXb+sve3VTsKFDbd5AXvcRY4TbPawQ5W7Aa6iK9W/yA10+zXvcHoGrA
6iMR94yI9eprBkqoeoxr2MHPk+8d9xXB16hY/h+OCPibkFFfPST9GDFcp0nk1JFH
b0bbpanBsxwN3IxTAL0a7iD2nxftZHjgiZib1lhdhLg35o9iou1V0fRPwdjepS3o
2TBvKhtNncUW/87ZhxhdkTI/iUvS0iem3KHUQXkM+ziOC5zGf+PYvMCuy2P0oSei
731aVOgxKbpEZHY0pTkuqG7U4+RWZ+KJEnxETcZWoCeY9DW/u2Dx5hukeZJbvmUo
111vBoziyocgKvKi5S3ctZaAwm2wNsE0TU/o5u9+Q5ST1wgsKJF+F0laCUQcDPwM
UyM5VznH31pChrlzRiUcsm0lMvDkx+JfTSBPOgzABMAcQ3YuTSk=
=e+q6
-----END PGP SIGNATURE-----

2
dist/manifest.txt vendored Normal file
View File

@ -0,0 +1,2 @@
fe92783ef775ccc5e32baefb26f951b7f37ed26ecbb4601a068e20b31bebadbb airgap.iso
b714c963bd8b1f3a38295821f0a3521bc64f97c1023c49d22a2e7433385b1a09 release.env

5
dist/release.env vendored Normal file
View File

@ -0,0 +1,5 @@
VERSION=2024.8.1
GIT_REF=ea623cc147741b0a753ce4ea7aabe512df9a2ef9
GIT_AUTHOR=Lance R. Vick
GIT_PUBKEY=6B61ECD76088748C70590D55E90A401336C8AAA9
GIT_TIMESTAMP=2024-08-08 00:34:41 -0700

55
rootfs/etc/init.d/S01syslogd Executable file
View File

@ -0,0 +1,55 @@
#!/bin/sh
DAEMON="syslogd"
PIDFILE="/var/run/$DAEMON.pid"
SYSLOGD_ARGS=""
# shellcheck source=/dev/null
[ -r "/etc/default/$DAEMON" ] && . "/etc/default/$DAEMON"
# BusyBox' syslogd does not create a pidfile, so pass "-n" in the command line
# and use "-m" to instruct start-stop-daemon to create one.
start() {
printf 'Starting %s: ' "$DAEMON"
# shellcheck disable=SC2086 # we need the word splitting
start-stop-daemon -b -m -S -q -p "$PIDFILE" -x "/sbin/$DAEMON" \
-- -n $SYSLOGD_ARGS
status=$?
if [ "$status" -eq 0 ]; then
echo "OK"
else
echo "FAIL"
fi
return "$status"
}
stop() {
printf 'Stopping %s: ' "$DAEMON"
start-stop-daemon -K -q -p "$PIDFILE"
status=$?
if [ "$status" -eq 0 ]; then
rm -f "$PIDFILE"
echo "OK"
else
echo "FAIL"
fi
return "$status"
}
restart() {
stop
sleep 1
start
}
case "$1" in
start|stop|restart)
"$1";;
reload)
# Restart, since there is no true "reload" feature.
restart;;
*)
echo "Usage: $0 {start|stop|restart|reload}"
exit 1
esac

55
rootfs/etc/init.d/S02klogd Executable file
View File

@ -0,0 +1,55 @@
#!/bin/sh
DAEMON="klogd"
PIDFILE="/var/run/$DAEMON.pid"
KLOGD_ARGS=""
# shellcheck source=/dev/null
[ -r "/etc/default/$DAEMON" ] && . "/etc/default/$DAEMON"
# BusyBox' klogd does not create a pidfile, so pass "-n" in the command line
# and use "-m" to instruct start-stop-daemon to create one.
start() {
printf 'Starting %s: ' "$DAEMON"
# shellcheck disable=SC2086 # we need the word splitting
start-stop-daemon -b -m -S -q -p "$PIDFILE" -x "/sbin/$DAEMON" \
-- -n $KLOGD_ARGS
status=$?
if [ "$status" -eq 0 ]; then
echo "OK"
else
echo "FAIL"
fi
return "$status"
}
stop() {
printf 'Stopping %s: ' "$DAEMON"
start-stop-daemon -K -q -p "$PIDFILE"
status=$?
if [ "$status" -eq 0 ]; then
rm -f "$PIDFILE"
echo "OK"
else
echo "FAIL"
fi
return "$status"
}
restart() {
stop
sleep 1
start
}
case "$1" in
start|stop|restart)
"$1";;
reload)
# Restart, since there is no true "reload" feature.
restart;;
*)
echo "Usage: $0 {start|stop|restart|reload}"
exit 1
esac

94
rootfs/etc/init.d/S02sysctl Executable file
View File

@ -0,0 +1,94 @@
#!/bin/sh
#
# This script is used by busybox and procps-ng.
#
# With procps-ng, the "--system" option of sysctl also enables "--ignore", so
# errors are not reported via syslog. Use the run_logger function to mimic the
# --system behavior, still reporting errors via syslog. Users not interested
# on error reports can add "-e" to SYSCTL_ARGS.
#
# busybox does not have a "--system" option neither reports errors via syslog,
# so the scripting provides a consistent behavior between the implementations.
# Testing the busybox sysctl exit code is fruitless, as at the moment, since
# its exit status is zero even if errors happen. Hopefully this will be fixed
# in a future busybox version.
PROGRAM="sysctl"
SYSCTL_ARGS=""
# shellcheck source=/dev/null
[ -r "/etc/default/$PROGRAM" ] && . "/etc/default/$PROGRAM"
# Files are read from directories in the SYSCTL_SOURCES list, in the given
# order. A file may be used more than once, since there can be multiple
# symlinks to it. No attempt is made to prevent this.
SYSCTL_SOURCES="/etc/sysctl.d/ /usr/local/lib/sysctl.d/ /usr/lib/sysctl.d/ /lib/sysctl.d/ /etc/sysctl.conf"
# If the logger utility is available all messages are sent to syslog, except
# for the final status. The file redirections do the following:
#
# - stdout is redirected to syslog with facility.level "kern.info"
# - stderr is redirected to syslog with facility.level "kern.err"
# - file dscriptor 4 is used to pass the result to the "start" function.
#
run_logger() {
# shellcheck disable=SC2086 # we need the word splitting
find $SYSCTL_SOURCES -maxdepth 1 -name '*.conf' -print0 2> /dev/null | \
xargs -0 -r -n 1 readlink -f | {
prog_status="OK"
while :; do
read -r file || {
echo "$prog_status" >&4
break
}
echo "* Applying $file ..."
/sbin/sysctl -p "$file" $SYSCTL_ARGS || prog_status="FAIL"
done 2>&1 >&3 | /usr/bin/logger -t sysctl -p kern.err
} 3>&1 | /usr/bin/logger -t sysctl -p kern.info
}
# If logger is not available all messages are sent to stdout/stderr.
run_std() {
# shellcheck disable=SC2086 # we need the word splitting
find $SYSCTL_SOURCES -maxdepth 1 -name '*.conf' -print0 2> /dev/null | \
xargs -0 -r -n 1 readlink -f | {
prog_status="OK"
while :; do
read -r file || {
echo "$prog_status" >&4
break
}
echo "* Applying $file ..."
/sbin/sysctl -p "$file" $SYSCTL_ARGS || prog_status="FAIL"
done
}
}
if [ -x /usr/bin/logger ]; then
run_program="run_logger"
else
run_program="run_std"
fi
start() {
printf '%s %s: ' "$1" "$PROGRAM"
status=$("$run_program" 4>&1)
echo "$status"
if [ "$status" = "OK" ]; then
return 0
fi
return 1
}
case "$1" in
start)
start "Running";;
restart|reload)
start "Rerunning";;
stop)
:;;
*)
echo "Usage: $0 {start|stop|restart|reload}"
exit 1
esac

24
rootfs/etc/init.d/S10udev Executable file
View File

@ -0,0 +1,24 @@
#!/bin/sh
case "$1" in
start)
printf "Populating %s using udev: " "${udev_root:-/dev}"
[ -e /proc/sys/kernel/hotplug ] && printf '\000\000\000\000' > /proc/sys/kernel/hotplug
/sbin/udevd -d || { echo "FAIL"; exit 1; }
udevadm trigger --type=subsystems --action=add
udevadm trigger --type=devices --action=add
udevadm settle --timeout=30 || echo "udevadm settle failed"
echo "done"
;;
stop)
# Stop execution of events
udevadm control --stop-exec-queue
killall udevd
;;
*)
echo "Usage: $0 {start|stop}"
exit 1
;;
esac
exit 0

20
rootfs/etc/init.d/S12pcscd Executable file
View File

@ -0,0 +1,20 @@
#!/bin/sh
case "$1" in
start)
/usr/sbin/pcscd -d || { echo "FAIL"; exit 1; }
killall pcscd
/usr/sbin/pcscd -d || { echo "FAIL"; exit 1; }
echo "done"
;;
stop)
# Stop execution of events
killall pcscd
;;
*)
echo "Usage: $0 {start|stop}"
exit 1
;;
esac
exit 0

70
rootfs/etc/init.d/S20urandom Executable file
View File

@ -0,0 +1,70 @@
#! /bin/sh
#
# Preserve the random seed between reboots. See urandom(4).
#
# Quietly do nothing if /dev/urandom does not exist
[ -c /dev/urandom ] || exit 0
URANDOM_SEED="/var/lib/random-seed"
# shellcheck source=/dev/null
[ -r "/etc/default/urandom" ] && . "/etc/default/urandom"
if pool_bits=$(cat /proc/sys/kernel/random/poolsize 2> /dev/null); then
pool_size=$((pool_bits/8))
else
pool_size=512
fi
init_rng() {
[ -f "$URANDOM_SEED" ] || return 0
printf 'Initializing random number generator: '
dd if="$URANDOM_SEED" bs="$pool_size" of=/dev/urandom count=1 2> /dev/null
status=$?
if [ "$status" -eq 0 ]; then
echo "OK"
else
echo "FAIL"
fi
return "$status"
}
save_random_seed() {
printf 'Saving random seed: '
status=1
if touch "$URANDOM_SEED.new" 2> /dev/null; then
old_umask=$(umask)
umask 077
dd if=/dev/urandom of="$URANDOM_SEED.tmp" bs="$pool_size" count=1 2> /dev/null
cat "$URANDOM_SEED" "$URANDOM_SEED.tmp" 2>/dev/null \
| sha256sum \
| cut -d ' ' -f 1 > "$URANDOM_SEED.new" && \
mv "$URANDOM_SEED.new" "$URANDOM_SEED" && status=0
rm -f "$URANDOM_SEED.tmp"
umask "$old_umask"
if [ "$status" -eq 0 ]; then
echo "OK"
else
echo "FAIL"
fi
else
echo "SKIP (read-only file system detected)"
fi
return "$status"
}
case "$1" in
start|restart|reload)
# Carry a random seed from start-up to start-up
# Load and then save the whole entropy pool
init_rng && save_random_seed;;
stop)
# Carry a random seed from shut-down to start-up
# Save the whole entropy pool
save_random_seed;;
*)
echo "Usage: $0 {start|stop|restart|reload}"
exit 1
esac

27
rootfs/etc/init.d/rcK Executable file
View File

@ -0,0 +1,27 @@
#!/bin/sh
# Stop all init scripts in /etc/init.d
# executing them in reversed numerical order.
#
for i in $(ls -r /etc/init.d/S??*) ;do
# Ignore dangling symlinks (if any).
[ ! -f "$i" ] && continue
case "$i" in
*.sh)
# Source shell script for speed.
(
trap - INT QUIT TSTP
set stop
. $i
)
;;
*)
# No sh extension, so fork subprocess.
$i stop
;;
esac
done

27
rootfs/etc/init.d/rcS Executable file
View File

@ -0,0 +1,27 @@
#!/bin/sh
# Start all init scripts in /etc/init.d
# executing them in numerical order.
#
for i in /etc/init.d/S??* ;do
# Ignore dangling symlinks (if any).
[ ! -f "$i" ] && continue
case "$i" in
*.sh)
# Source shell script for speed.
(
trap - INT QUIT TSTP
set start
. $i
)
;;
*)
# No sh extension, so fork subprocess.
$i start
;;
esac
done

View File

@ -1,11 +1,5 @@
# /etc/inittab
#
# Copyright (C) 2001 Erik Andersen <andersen@codepoet.org>
#
# Note: BusyBox init doesn't support runlevels. The runlevels field is
# completely ignored by BusyBox init. If you want runlevels, use
# sysvinit.
#
# Format for each entry: <id>:<runlevels>:<action>:<process>
#
# id == tty to run on, or empty for /dev/console
@ -14,16 +8,15 @@
# process == program to run
# Startup the system
::sysinit:/bin/mount -t devtmpfs devtmpfs /dev
::sysinit:/bin/mkdir -p /proc /run /dev/pts /dev/shm /sys
::sysinit:/bin/mount -t sysfs sysfs /sys
::sysinit:/bin/mount -t proc proc /proc
::sysinit:/bin/mount -o remount,rw /
::sysinit:/bin/mkdir -p /dev/pts /dev/shm
::sysinit:/bin/mount -a
::sysinit:/sbin/swapon -a
null::sysinit:/bin/ln -sf /proc/self/fd /dev/fd
null::sysinit:/bin/ln -sf /proc/self/fd/0 /dev/stdin
null::sysinit:/bin/ln -sf /proc/self/fd/1 /dev/stdout
null::sysinit:/bin/ln -sf /proc/self/fd/2 /dev/stderr
::sysinit:/bin/hostname -F /etc/hostname
# now run any rc scripts
::sysinit:/etc/init.d/rcS
@ -36,5 +29,4 @@ null::sysinit:/bin/ln -sf /proc/self/fd/2 /dev/stderr
# Stuff to do before rebooting
::shutdown:/etc/init.d/rcK
::shutdown:/sbin/swapoff -a
::shutdown:/bin/umount -a -r

View File

@ -3,8 +3,7 @@ export PATH="/usr/local/bin:/bin:/sbin:/usr/bin:/usr/sbin"
export PS1="[\h \t] \\$ "
export GNUPGHOME=/.gnupg
source /etc/environment
dmesg -n1
cd /root
clear
cat << "EOF"
_ _ ___ ____
@ -19,5 +18,5 @@ echo " - Version: $VERSION"
echo " - Date: $GIT_TIMESTAMP"
echo " - Committer: $GIT_AUTHOR"
echo " - Commit: $GIT_REF"
echo " - Key: $GIT_KEY"
echo " - Key: $GIT_PUBKEY"
echo ""

View File

@ -1,12 +0,0 @@
KERNEL!="sd[a-z][0-9]", GOTO="sd_cards_auto_mount_end"
# Global mount options
ACTION=="add", ENV{mount_options}="relatime"
# Filesystem specific options
ACTION=="add", IMPORT{program}="/sbin/blkid -o udev -p %N"
ACTION=="add", ENV{ID_FS_TYPE}=="vfat|ntfs", ENV{mount_options}="$env{mount_options},utf8,flush,user,umask=0000"
ACTION=="add", RUN+="/bin/mkdir -p /media/sd-%k", RUN+="/bin/mount -o $env{mount_options} /dev/%k /media/sd-%k"
ACTION=="add", RUN+="/usr/local/bin/autorun /media/sd-%k"
ACTION=="remove", RUN+="/bin/umount -l /media/sd-%k", RUN+="/bin/rmdir /media/sd-%k"
LABEL="sd_cards_auto_mount_end"

2
rootfs/init Executable file
View File

@ -0,0 +1,2 @@
#!/bin/sh
exec /bin/init

View File

@ -0,0 +1,15 @@
KERNEL!="mmcblk[0-9]p[0-9]|sd[a-z][0-9]", GOTO="automount_end"
ACTION=="add", PROGRAM!="/sbin/blkid %N", GOTO="automount_end"
IMPORT{program}="/sbin/blkid -o udev -p %N"
ENV{ID_FS_LABEL}!="", ENV{dir_name}="%E{ID_FS_LABEL}"
ENV{ID_FS_LABEL}=="", ENV{dir_name}="%k"
ACTION=="add", IMPORT{program}="/sbin/blkid -o udev -p %N"
ACTION=="add", ENV{ID_FS_TYPE}=="vfat", ENV{mount_options}="relatime,utf8,flush,user,umask=0000"
ACTION=="add", RUN+="/bin/mkdir -p /media/%E{dir_name}", RUN+="/bin/mount -o $env{mount_options} /dev/%k /media/%E{dir_name}"
ACTION=="add", RUN+="/usr/local/bin/autorun /media/%E{dir_name}"
ACTION=="remove", ENV{dir_name}!="", RUN+="/bin/umount -l /media/%E{dir_name}", RUN+="/bin/rmdir /media/%E{dir_name}"
LABEL="automount_end"

3
sdcard/autorun.sh Normal file
View File

@ -0,0 +1,3 @@
#!/bin/bash
echo "Autorun.sh executed"