Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions fca-mount
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env bash

set -euo pipefail
for partition_id in $(fca-partitions); do
sudo mkdir -p "/mnt/${partition_id}"
sudo mount "/dev/disk/by-uuid/${partition_id}" "/mnt/${partition_id}"
done

fca-sync
17 changes: 17 additions & 0 deletions fca-partitions
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/usr/bin/env bash

set -euo pipefail

partitions_found=0

for part in "1fa86f97-8161-433a-9f03-7ff80877932c" "caa1991c-af27-47c1-8148-5eb528c73376" "3fc9965e-fd79-4a4d-8a80-4d3b57acfc27"; do
if [[ -L "/dev/disk/by-uuid/${part}" ]]; then
echo "${part}"
partitions_found=$((partitions_found+1))
fi
done

if [[ "$partitions_found" == "0" ]]; then
echo "No CA stick found!" >&2
exit 1
fi
18 changes: 18 additions & 0 deletions fca-sync
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/usr/bin/env bash

set -euo pipefail

for partition in $(fca-partitions); do
cd "/mnt/${partition}/ca-data"
for other in $(fca-partitions); do
if [ "$partition" != "$other" ]; then
if ! git remote | grep -q "^${other}$"; then
git remote add "$other" "/mnt/${other}/ca-data"
fi
git fetch "${other}"
git merge --ff-only "${other}/main"
fi
done
done

sync
138 changes: 138 additions & 0 deletions fca-tools
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
#!/usr/bin/env bash
#
# Operations:
# init-root create the root CA
# sign-intermediate <csr-file> sign an intermediate CSR
# verify <cert-file> verify a certificate against the root
# list show what's in the depot
#
# Passphrase handling:
# - Interactive by default (certstrap prompts).
# - ROOT_CA_PASSPHRASE=<passphrase>

set -euo pipefail

readonly DEPOT="$(fca-working-directory)/ca-data"
readonly ORG="Famedly GmbH"
readonly CURVE="P-384"
readonly ROOT_CN="Famedly GmbH Root CA 2026"
readonly ROOT_EXPIRES="10 years"
readonly INT_EXPIRES="5 years"

usage() {
sed -n '3,/^set -euo pipefail$/p' "$0" | sed -n 's/^# \{0,1\}//p' >&2
exit "${1:-2}"
}

slug_for_cn() { printf '%s' "${1// /_}"; }
root_slug() { slug_for_cn "$ROOT_CN"; }

build_pass_args() {
if [[ -n "${ROOT_CA_PASSPHRASE:-}" ]]; then
printf '%s\n%s\n' "--passphrase" "$ROOT_CA_PASSPHRASE"
fi
}

assert_no_clobber() {
[[ -e "$1" ]] && die "refusing to overwrite existing file: $1"
return 0
}

die() {
echo "$*"
exit 1
}

cmd_init_root() {
mkdir -p "$DEPOT"
local slug="$(root_slug)"
assert_no_clobber "$DEPOT/$slug.key"
assert_no_clobber "$DEPOT/$slug.crt"

local pass_args=()
while IFS= read -r line; do pass_args+=("$line"); done < <(build_pass_args)

certstrap --depot-path "$DEPOT" init \
--common-name "$ROOT_CN" \
--organization "$ORG" \
--curve "$CURVE" \
--expires "$ROOT_EXPIRES" \
--path-length 1 \
"${pass_args[@]}"
}

cmd_sign_intermediate() {
local csr_file="$1"
[[ -f "$csr_file" ]] || die "CSR file not found: $csr_file"

local root_slug="$(root_slug)"
[[ -f "$DEPOT/$root_slug.key" ]] || die "root key not found at $DEPOT/$root_slug.key"

local cn="$(openssl req -in $csr_file -noout -subject | sed 's/subject=CN=//')"
[[ -z "$cn" ]] && die "Couldn't decode CN from $csr_file"

local int_slug="$(slug_for_cn "$cn")"
assert_no_clobber "$DEPOT/$int_slug.crt"

local pass_args=()
while IFS= read -r line; do pass_args+=("$line"); done < <(build_pass_args)

certstrap --depot-path "$DEPOT" sign \
--CA "$ROOT_CN" \
--intermediate \
--path-length 0 \
--expires "$INT_EXPIRES" \
--csr "$csr_file" \
"${pass_args[@]}" \
"$cn"
}

cmd_verify() {
local cert="$1"
[[ -f "$cert" ]] || die "cert not found: $cert"
local root_slug root_crt
root_slug="$(root_slug)"
root_crt="$DEPOT/$root_slug.crt"
[[ -f "$root_crt" ]] || die "root cert not found at $root_crt"

openssl verify -CAfile "$root_crt" "$cert"
openssl x509 -in "$cert" -noout -subject -issuer -dates -ext basicConstraints,keyUsage,subjectKeyIdentifier,authorityKeyIdentifier
}

cmd_list() {
[[ -d "$DEPOT" ]] || die "depot $DEPOT does not exist"
echo "depot: $DEPOT"
echo
ls -lh "$DEPOT"/*
local root_crt; root_crt="$DEPOT/$(root_slug).crt"
if [[ -f "$root_crt" ]]; then
echo
openssl x509 -in "$root_crt" -noout -subject -dates -ext basicConstraints,keyUsage
fi
local root_crl; root_crl="$DEPOT/$(root_slug).crl"
if [[ -f "$root_crl" ]]; then
echo
openssl crl -in "$root_crl" -noout -text
fi
}

[[ $# -ge 1 ]] || usage

sub="$1"; shift
case "$sub" in
-h|--help|help)
usage 0
;;
init-root|sign-intermediate|verify|list)
;;
*)
die "unknown subcommand: $sub (try $0 --help)"
;;
esac

case "$sub" in
init-root) [[ $# -eq 0 ]] || die "init-root takes no args"; cmd_init_root ;;
sign-intermediate) [[ $# -eq 1 ]] || die "usage: $0 sign-intermediate CSR"; cmd_sign_intermediate "$1" ;;
verify) [[ $# -eq 1 ]] || die "usage: $0 verify CERT"; cmd_verify "$1" ;;
list) [[ $# -eq 0 ]] || die "list takes no args"; cmd_list ;;
esac
6 changes: 6 additions & 0 deletions fca-working-directory
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/usr/bin/env bash

set -euo pipefail

partition="$(fca-partitions | head -n 1)"
echo "/mnt/${partition}"
9 changes: 9 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,15 @@
{
formatter = pkgs.nixpkgs-fmt;
packages = {
# Famedly CA Scripts
fca-mount = pkgs.writeShellScriptBin "fca-mount" (builtins.readFile ./fca-mount);
fca-partitions = pkgs.writeShellScriptBin "fca-partitions" (builtins.readFile ./fca-partitions);
fca-sync = pkgs.writeShellScriptBin "fca-sync" (builtins.readFile ./fca-sync);
fca-tools = pkgs.writeShellScriptBin "fca-tools" (builtins.readFile ./fca-tools);
fca-working-directory = pkgs.writeShellScriptBin "fca-working-directory" (
builtins.readFile ./fca-working-directory
);
# Famedly OpenPGP Scripts
fos-export = pkgs.writeShellScriptBin "fos-export" (builtins.readFile ./fos-export);
fos-flash = pkgs.writeShellScriptBin "fos-flash" (builtins.readFile ./fos-flash);
fos-generate = pkgs.writeShellScriptBin "fos-generate" (builtins.readFile ./fos-generate);
Expand Down
2 changes: 1 addition & 1 deletion fos-partitions
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ for part in "B9C8-D9A6" "EC3D-3102" "F055-B17B" "F665-64A4"; do
done

if [[ "$partitions_found" == "0" ]]; then
echo "No stick found!" >&2
echo "No OCA stick found!" >&2
exit 1
fi
9 changes: 9 additions & 0 deletions iso.nix
Original file line number Diff line number Diff line change
Expand Up @@ -147,9 +147,11 @@ in
jq
kdePackages.falkon
kdePackages.okular
kdePackages.partitionmanager
nano
neovim
openpgp-card-tools
openssl
pcsc-tools
pwgen
rusty-diceware
Expand All @@ -159,6 +161,13 @@ in
wayland-utils
wl-clipboard

# Famedly CA Scripts
flake.packages.${stdenv.hostPlatform.system}.fca-mount
flake.packages.${stdenv.hostPlatform.system}.fca-partitions
flake.packages.${stdenv.hostPlatform.system}.fca-sync
flake.packages.${stdenv.hostPlatform.system}.fca-tools
flake.packages.${stdenv.hostPlatform.system}.fca-working-directory

# Famedly OpenPGP Scripts
flake.packages.${stdenv.hostPlatform.system}.fos-export
flake.packages.${stdenv.hostPlatform.system}.fos-flash
Expand Down
Loading