Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Package split #161

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
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
8 changes: 8 additions & 0 deletions debian/changelog
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
safeboot (0.9) unstable; urgency=medium

* Add enrollment server functionality
* Add helper scripts for enrolled host credential bootstrapping
* Split Debian packaging

-- Nico Williams <[email protected]> Wed, 24 Nov 2021 16:22:53 -0600

safeboot (0.8) unstable; urgency=medium

* `tpm2-attest` and `attest-server` to perform attestations
Expand Down
49 changes: 47 additions & 2 deletions debian/control
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,55 @@ Homepage: https://github.com/osresearch/safeboot/
#Vcs-Git: https://salsa.debian.org/debian/safeboot.git

Package: safeboot
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}, efitools, opensc, yubico-piv-tool, libengine-pkcs11-openssl, uuid, binutils, libqrencode-dev, libjson-c4, libcurl4
Architecture: all
Depends: ${shlibs:Depends}, ${misc:Depends}, binutils, safeboot-tpm2-tools | tpm2-tools (>= 5.1.1), safeboot-tpm2-totp | tpm2-totp (>= 3.1.0)
Description: Common (core) package for Safeboot
Safeboot is a collection of utilities and services for securing the boot
process.

Package: safeboot-boot
Architecture: all
Breaks: safeboot (<<0.9)
Replaces: safeboot (<<0.9)
Depends: ${shlibs:Depends}, ${misc:Depends}, safeboot, efitools, opensc, yubico-piv-tool, libengine-pkcs11-openssl, uuid, binutils, libqrencode-dev, libjson-c4, libcurl4
Description: Boot Linux more safely
Makes the Linux boot process slightly safer by enabling UEFI Secure Boot,
signing kernel and initrd with Yubikey hardware tokens, storing disk
encryption secrets in the TPM, and preventing persistence with
dmverity read-only root filesystems.

Package: safeboot-attest-client
Architecture: all
Breaks: safeboot (<<0.9)
Replaces: safeboot (<<0.9)
Depends: ${shlibs:Depends}, ${misc:Depends}, safeboot
Description: Safeboot attestation client
Attestation client for Safeboot, which is intended to be used for securely
fetching local filesystem encryption keys (including for the root
filesystem), and other secrets (including device credentials).

Package: safeboot-attest-server
Architecture: all
Breaks: safeboot (<<0.9)
Replaces: safeboot (<<0.9)
Depends: ${shlibs:Depends}, ${misc:Depends}, safeboot
Description: Safeboot attestation server
Enrollment and attestation server for Safeboot, which is intended to be
used for securely fetching local filesystem encryption keys (including for
the root filesyste), and other secrets (including device credentials).

Package: safeboot-tpm2-tools
Architecture: any
Breaks: safeboot (<<0.9)
Replaces: safeboot (<<0.9)
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: tpm2-tools at version needed by Safeboot
Safeboot depends on more recent versions of tpm2-tools than are packaged.

Package: safeboot-tpm2-totp
Architecture: any
Breaks: safeboot (<<0.9)
Replaces: safeboot (<<0.9)
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: tpm2-totp at version needed by Safeboot
Safeboot depends on more recent versions of tpm2-totp than are packaged.
6 changes: 6 additions & 0 deletions debian/safeboot-attest-client.install
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# shell script commands
sbin/tpm2-attest usr/sbin/
sbin/tpm2-pcr-validate usr/sbin/

# libexec shell scripts
sbin/getkeytab usr/libexec/safeboot/
14 changes: 14 additions & 0 deletions debian/safeboot-attest-server.install
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# shell scripts in the tree
sbin/attest-enroll usr/sbin/
sbin/attest-verify
sbin/attest-server usr/sbin/
# XXX
sbin/attest-server-sub.py usr/sbin/

# These are delivered by safeboot-attest-client for now until we split them up
# sbin/tpm2-attest usr/sbin/
# sbin/tpm2-pcr-validate usr/sbin/

# libexec shell scripts
sbin/gencert usr/libexec/safeboot/
sbin/genkeytab usr/libexec/safeboot/
13 changes: 0 additions & 13 deletions debian/install → debian/safeboot-boot.install
Original file line number Diff line number Diff line change
@@ -1,26 +1,13 @@
# shell scripts in the tree
sbin/safeboot usr/sbin/
sbin/safeboot-tpm-unseal usr/sbin/
sbin/tpm2-attest usr/sbin/
sbin/tpm2-pcr-validate usr/sbin/

# configuration files and helper functions
safeboot.conf etc/safeboot/
functions.sh etc/safeboot/

# TPM certs and a script to refresh them
tpm-certs.txt etc/safeboot/
refresh-certs etc/safeboot/
certs/* etc/safeboot/certs/

# Compiled with modifications from source
# to add support for the pkcs11 engine (sbsign),
# hostnames and small qrcodes (tpm2-totp),
# and bundle all tpm2 applications in a single script (tpm2)
bin/sbsign.safeboot usr/sbin/
bin/sign-efi-sig-list.safeboot usr/sbin/
bin/tpm2-totp usr/sbin/
bin/tpm2 usr/sbin/

# scripts to interface with secure boot in the initramfs
initramfs/hooks/dmverity-root etc/initramfs-tools/hooks/
Expand Down
5 changes: 5 additions & 0 deletions debian/safeboot-tpm2-tools.install
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Compiled with modifications from source
# to add support for the pkcs11 engine (sbsign),
# hostnames and small qrcodes (tpm2-totp),
# and bundle all tpm2 applications in a single script (tpm2)
bin/tpm2 usr/sbin/
5 changes: 5 additions & 0 deletions debian/safeboot-tpm2-totp.install
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Compiled with modifications from source
# to add support for the pkcs11 engine (sbsign),
# hostnames and small qrcodes (tpm2-totp),
# and bundle all tpm2 applications in a single script (tpm2)
bin/tpm2-totp usr/sbin/
8 changes: 8 additions & 0 deletions debian/safeboot.install
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Shell functions library
functions.sh etc/safeboot/
functions.sh usr/lib/safeboot/

# TPM certs and a script to refresh them
tpm-certs.txt usr/share/safeboot/
refresh-certs usr/share/safeboot/
certs/* usr/share/safeboot/certs/
2 changes: 1 addition & 1 deletion debian/source/format
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.0 (quilt)
3.0 (native)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not familiar with these formats and had copied from a different debian package. what's the difference?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did what Thomas told me :) I'm not familiar either.

11 changes: 10 additions & 1 deletion functions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,17 @@ safeboot_dir() {
[[ -n $1 ]] \
|| die "Internal error in caller of safeboot_dir"
case "$1" in
bin) echo "$TOP/bin";;
bin) echo "$TOP/sbin";;
lib) echo "$TOP/lib";;
libexec|share)
if [[ $TOP = /usr && -d /usr/${1}/safeboot ]]; then
echo "/usr/${1}/safeboot"
elif [[ -d $TOP/${1} ]]; then
echo "$TOP/${1}"
else
echo "/etc/safeboot"
fi;;
certs) echo "$(safeboot_dir libexec)/certs";;
etc) if [[ $TOP = /usr ]]; then
echo "/etc/safeboot"
elif [[ -d $TOP/etc/safeboot ]]; then
Expand Down
8 changes: 8 additions & 0 deletions sbin/attest-enroll
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,21 @@ shopt -s extglob
PROG=${0##*/}
BINDIR=$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")
TOP=$(dirname "$BINDIR")
if [[ $TOP = /usr ]]; then
PATH=${TOP}/libexec/safeboot:$PATH
else
PATH=${TOP}/libexec/:$PATH
fi

if [[ -s $TOP/lib/safeboot/functions.sh ]]; then
# shellcheck source=functions.sh
. "$TOP/lib/safeboot/functions.sh"
elif [[ -s $TOP/functions.sh ]]; then
# shellcheck source=functions.sh
. "$TOP/functions.sh"
elif [[ -s /etc/safeboot/functions.sh ]]; then
# shellcheck source=functions.sh
. /etc/safeboot/functions.sh
else
echo "Unable to find Safeboot function library" 1>&2
exit 1
Expand Down
161 changes: 128 additions & 33 deletions sbin/gencert
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,36 @@ if [[ -s $TOP/lib/safeboot/functions.sh ]]; then
elif [[ -s $TOP/functions.sh ]]; then
# shellcheck disable=SC1090 source=functions.sh
. "$TOP/functions.sh"
elif [[ -s /etc/safeboot/functions.sh ]]; then
# shellcheck source=functions.sh
. /etc/safeboot/functions.sh
else
echo "Unable to find Safeboot function library" 1>&2
exit 1
fi

GENCERT_CRED=PEM-FILE:/etc/safeboot/gencert-ca.pem
GENCERT_CA_PRIV=
GENCERT_CA_CERT=PEM-FILE:/etc/safeboot/gencert-ca.pem
GENCERT_REALM=
GENCERT_KEY_BITS=2048
GENCERT_INCLUDE_SAN_PKINIT=true
GENCERT_INCLUDE_SAN_DNSNAME=false
GENCERT_EKUS=()
GENCERT_X509_TOOLING=OpenSSL # Or Heimdal
declare -a GENCERT_EKUS
declare -A GENCERT_DOMAIN_REALM
declare -A POLICIES
GENCERT_EKUS=()
GENCERT_DOMAIN_REALM=()

cf=$(safeboot_file etc enroll.conf)
if [[ -n $cf && -f $cf ]]; then
if [[ -n ${SAFEBOOT_ENROLL_CONF:-} ]]; then
# shellcheck disable=SC1090
. "$cf"
export SAFEBOOT_ENROLL_CONF="$cf"
. "$SAFEBOOT_ENROLL_CONF"
else
cf=$(safeboot_file etc enroll.conf)
if [[ -n $cf && -f $cf ]]; then
# shellcheck disable=SC1090
. "$cf"
fi
fi

die() { echo "skip: $*"; echo >&2 "Error: $PROG" "$@" ; exit 1 ; }
Expand All @@ -43,6 +55,23 @@ outdir=$2
hostname=$3
shift 3

${GENCERT_INCLUDE_SAN_PKINIT} \
|| ${GENCERT_INCLUDE_SAN_DNSNAME} \
|| die 'One of GENCERT_INCLUDE_SAN_{PKINIT,DNSNAME} must be set to true'

declare -a hxtool_ca_opts
declare -a openssl_x509_opts

hxtool_ca_opts=("--ca-certificate=$GENCERT_CA_CERT")
openssl_x509_opts=("-CA" "$GENCERT_CA_CERT")

if [[ -n $GENCERT_CA_PRIV ]]; then
[[ -n $GENCERT_CA_CERT ]] \
|| die "GENCERT_CA_CERT is not set"
hxtool_ca_opts+=("--ca-private-key=$GENCERT_CA_PRIV")
openssl_x509_opts+=("-CAkey" "$GENCERT_CA_PRIV")
fi

if [[ -z $GENCERT_REALM ]]; then
domain=${hostname}
while [[ $domain = *.*.* ]]; do
Expand All @@ -60,46 +89,112 @@ if [[ -z $GENCERT_REALM ]]; then
|| die "Could not determine realm name for $hostname"
fi

sans=()

${GENCERT_INCLUDE_SAN_PKINIT} \
&& sans+=(--pk-init-principal="host/$hostname@$GENCERT_REALM")
&& hxtool_ca_opts+=(--pk-init-principal="host/$hostname@$GENCERT_REALM")

${GENCERT_INCLUDE_SAN_DNSNAME} \
&& sans+=(--hostname="$hostname")
&& hxtool_ca_opts+=(--hostname="$hostname")

ekus=()
if ((${#GENCERT_EKUS[@]} > 0)); then
for eku in "${GENCERT_EKUS[@]}"; do
ekus+=(--eku="$eku")
hxtool_ca_opts+=(--eku="$eku")
done
fi

cat > cert-extensions <<EOF
[client_cert]
basicConstraints=CA:FALSE
keyUsage=digitalSignature,keyEncipherment,keyAgreement
extendedKeyUsage=@eku_section
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
issuerAltName=issuer:copy
subjectAltName=critical,@subject_alt_section

[eku_section]
extendedKeyUsage.800=1.3.6.1.5.2.3.4
extendedKeyUsage.801=1.3.6.1.5.5.7.3.2
$(
for i in "${!GENCERT_EKUS[@]}"; do
printf 'extendedKeyUsage.%s=%s\n' \
"$i" "${GENCERT_EKUS[1]}"
done
)

[subject_alt_section]
$(${GENCERT_INCLUDE_SAN_DNSNAME} \
&& printf 'DNS.1=${ENV::HOST_NAME}\n')
$(${GENCERT_INCLUDE_SAN_PKINIT} \
&& printf 'otherName.2=1.3.6.1.5.2.2;SEQUENCE:princ_name\n')

[princ_name]
realm=EXP:0,GeneralString:\${ENV::GENCERT_REALM}
principal_name=EXP:1,SEQUENCE:principal_seq

[principal_seq]
name_type=EXP:0,INTEGER:1
name_string=EXP:1,SEQUENCE:principals

[principals]
princ0=GeneralString:\${ENV::SERVICE}
princ1=GeneralString:\${ENV::HOST_NAME}
EOF

# Generate the private key (and a CSR, which is kind of unnecessary, but...)
trap 'rm -f cert-req.der cert-key.pem' EXIT
hxtool request-create \
--subject='' \
--generate-key=rsa \
--key-bits="$GENCERT_KEY_BITS" \
--key="PEM-FILE:$PWD/cert-key.pem" \
cert-req.der \
|| die "Could not generate RSA key!"
# Format and sign the end-entity certificate
hxtool issue-certificate \
--type=pkinit-client \
--ca-certificate="$GENCERT_CRED" \
--subject= \
"${sans[@]}" \
"${ekus[@]}" \
--ku=digitalSignature \
--lifetime=10y \
--req="PKCS10:cert-req.der" \
--certificate=PEM-FILE:cert.pem \
|| die "skip: Could not issue PKINIT certificate for impersonation!"
trap 'rm -f cert-extensions cert-req cert-key.pem' EXIT

# Try Heimdal's hxtool
case "$GENCERT_X509_TOOLING" in
Heimdal)
hxtool request-create \
--subject='' \
--generate-key=rsa \
--key-bits="$GENCERT_KEY_BITS" \
--key="PEM-FILE:cert-key.pem" \
cert-req 2>/dev/null \
|| die "Could not generate a key and make a CSR"
! hxtool issue-certificate \
"${hxtool_ca_opts[@]}" \
--type=pkinit-client \
--subject= \
--ku=digitalSignature \
--lifetime=10y \
--req="PKCS10:cert-req" \
--certificate=PEM-FILE:cert.pem 2>/dev/null \
|| die "Could not issue certificate"
;;
OpenSSL)
openssl genrsa \
-out cert-key.pem 2048 \
|| die "Could not make an RSA key"
openssl req \
-new \
-batch \
-subj '/' \
-key cert-key.pem \
-out cert-req \
|| die "Could not make a CSR"

export GENCERT_REALM
export HOST_NAME="$hostname"
export SERVICE="host"

openssl x509 \
-set_serial "0x$(_rand 16 | bin2hex)" \
"${openssl_x509_opts[@]}" \
-req \
-in cert-req \
-extensions client_cert \
-extfile cert-extensions \
-days 365 \
-out cert.pem \
|| die "Could not make a certificate"
esac


# Append the issuer certificate and any other certs in that file to the output
# so that the full chain is included.
openssl crl2pkcs7 -nocrl -certfile "${GENCERT_CRED#*:}" \
openssl crl2pkcs7 -nocrl -certfile "${GENCERT_CA_CERT#*:}" \
| openssl pkcs7 -print_certs >> cert.pem

grep -q PRIVATE cert.pem && die "Private key in cert file?!"
Expand Down
Loading