Files
LithosAnanke/ci/pki/make-ca.sh
T
Claude 3bd81097e1 chore(license): an SPDX header on every source file that had none (LicenseRef-Starship-1.0) [skip ci]
The header scan (Captain Bob, 2026-11-10): 788 source files -- 351 with the
SL-1.0 header, 12 with the old name (docs/working/experiments, kept by
ruling), 31 under someone else's licence (tools/kconfig, Linux's, GPL-2.0:
kept), and 394 with none. Ruled: the SPDX form; capsules (.4th, .f18) and
proofs (.thy) left for a ruling of their own (mkcapsule's 64x16 block format,
content-addressed capsules).

253 files now begin
    SPDX-License-Identifier: LicenseRef-Starship-1.0
    Copyright (c) 2023-2026 Robert A. James
as a /* */ block (C, headers, assembly, linker scripts) or # lines (scripts,
Makefiles, Kconfig; below a shebang or a coding line); tools/mkcapsule.c,
which had the copyright line, gets the SPDX line only.

Not touched: docs/working/ (archive and old campaign material, as the
ruling kept the experiments); v4/system/post_cases.c (generated by
v4/tools/mkpost.py, "do not edit" -- the generator has the header).

Comments only: the kernel builds on amd64, aarch64, riscv64; make -C v4
test-32: 39 programs, 0 failures; every changed script parses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-10 04:12:49 +00:00

87 lines
4.4 KiB
Bash
Executable File

#!/bin/bash
# SPDX-License-Identifier: LicenseRef-Starship-1.0
# Copyright (c) 2023-2026 Robert A. James
# make-ca.sh -- the StarshipOS capsule-signing PKI, made once, on the CI box (Captain Bob,
# 2026-11-07: "New root CA on the CI box. Valid StarshipOS rather than snake oil intermediate").
#
# StarshipOS Root CA Ed25519, 20 years, self-signed. Its key never leaves this box:
# not in the repository, not in Gitea, not in any image. Its
# certificate (public) is ci/pki/starshipos-root-ca.pem, made on
# 2026-11-07, SHA-256 in starshipos-root-ca.sha256; every release
# attaches it.
# StarshipOS Capsule Signing Ed25519, 10 years, signed by the root; CA:TRUE, pathlen:0.
# Its certificate is built into every image (capsules/pki/
# starshipos-intermediate.der) and checks each capsule at boot;
# its key signs the capsules (mkcapsule --sign-key), in CI from
# the repository secret CAPSULE_SIGN_KEY.
#
# Replaces the offline LithosAnanke Root CA and its snakeoil intermediate (FABRIC-2.md,
# Milestone 6) for every build. Run as root:
#
# sudo ci/pki/make-ca.sh [dir] # dir defaults to /var/lib/starshipos-ca
#
# It refuses to overwrite an existing CA. When it is done it prints the two certificates (public:
# paste them where they are wanted) and says how to put the signing key into Gitea. With
# GITEA_TOKEN set (a token that may administer the repository), it stores the secret itself.
set -euo pipefail
umask 077
dir=${1:-/var/lib/starshipos-ca}
repo=${GITEA_REPO:-rajames/LithosAnanke}
api=${GITEA_API:-https://gitea.starshipos-f18.org/api/v1}
command -v openssl >/dev/null || { echo "make-ca: needs openssl" >&2; exit 1; }
[ -e "$dir/root/root.key" ] && { echo "make-ca: $dir already holds a CA; not overwriting it" >&2; exit 1; }
mkdir -p "$dir/root" "$dir/signing"
cd "$dir"
cat > ca.cnf <<'CNF'
[ req ]
distinguished_name = dn
prompt = no
[ dn ]
[ root_ext ]
basicConstraints = critical, CA:TRUE
keyUsage = critical, keyCertSign, cRLSign
subjectKeyIdentifier = hash
[ signing_ext ]
basicConstraints = critical, CA:TRUE, pathlen:0
keyUsage = critical, keyCertSign, cRLSign, digitalSignature
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always
CNF
# the root
openssl genpkey -algorithm ed25519 -out root/root.key
openssl req -new -x509 -key root/root.key -days 7305 -config ca.cnf -extensions root_ext \
-subj "/O=StarshipOS/CN=StarshipOS Root CA" -out root/root.pem
# the capsule-signing intermediate, signed by the root
openssl genpkey -algorithm ed25519 -out signing/signing.key
openssl req -new -key signing/signing.key -config ca.cnf \
-subj "/O=StarshipOS/CN=StarshipOS Capsule Signing" -out signing/signing.csr
openssl x509 -req -in signing/signing.csr -CA root/root.pem -CAkey root/root.key \
-CAcreateserial -days 3652 -extfile ca.cnf -extensions signing_ext -out signing/signing.pem
openssl x509 -in signing/signing.pem -outform DER -out signing/starshipos-intermediate.der
openssl verify -CAfile root/root.pem signing/signing.pem
chmod 700 root signing; chmod 600 root/* signing/*
if [ -n "${GITEA_TOKEN:-}" ]; then
python3 -c 'import json,sys; print(json.dumps({"data": open(sys.argv[1]).read()}))' signing/signing.key |
curl -fsS -o /dev/null -X PUT -H "Authorization: token $GITEA_TOKEN" -H 'Content-Type: application/json' \
"$api/repos/$repo/actions/secrets/CAPSULE_SIGN_KEY" -d @- &&
echo "make-ca: stored the signing key as $repo's secret CAPSULE_SIGN_KEY"
else
echo "make-ca: put $dir/signing/signing.key, whole, into $repo's Actions secret CAPSULE_SIGN_KEY"
echo " (Settings -> Actions -> Secrets), or run again with GITEA_TOKEN set -- after"
echo " removing $dir, since it refuses to overwrite a CA."
fi
echo
echo "=== The root certificate (public) -- $dir/root/root.pem"
cat root/root.pem
echo "=== The capsule-signing certificate (public) -- $dir/signing/signing.pem"
cat signing/signing.pem
echo "=== Fingerprints"
openssl x509 -in root/root.pem -noout -fingerprint -sha256 -subject -enddate
openssl x509 -in signing/signing.pem -noout -fingerprint -sha256 -subject -issuer -enddate