[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

[PATCH 1/3] Add byhand script to perform code signing



It takes a tarball of code objects and generates a tarball of
corresponding detached PKCS#7 signatures (with '.sig' suffixes).

It will sign:
- EFI binaries (*.efi, vmlinuz-*) using pesign
- Linux kernel modules (*.ko) using sign-file from linux-kbuild-<version>

Currently it should work with private key files and certificates.  It
may be able to sign kernel modules with a key on a PKCS#11 device.
It definitely can't sign EFI binaries using a PKCS#11 device yet.
---
 scripts/debian/byhand-code-sign | 148 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 148 insertions(+)
 create mode 100755 scripts/debian/byhand-code-sign

diff --git a/scripts/debian/byhand-code-sign b/scripts/debian/byhand-code-sign
new file mode 100755
index 000000000000..8038813ed83c
--- /dev/null
+++ b/scripts/debian/byhand-code-sign
@@ -0,0 +1,148 @@
+#!/bin/bash
+
+set -u
+set -e
+set -o pipefail
+
+if [ $# -lt 5 ]; then
+	echo "Usage: $0 filename version arch changes_file suite"
+	exit 1
+fi
+
+IN_TARBALL="$1"	# Tarball to read, compressed with xz
+VERSION="$2"
+ARCH="$3"
+CHANGES="$4"	# Changes file for the upload
+SUITE="$5"
+
+error() {
+	echo >&2 "E: $*"
+	exit 1
+}
+
+export OPENSSL_CONF=/dev/null
+
+# Read dak configuration for security or main archive
+case "$SUITE" in
+    *-security)
+	configdir="/srv/security-master.debian.org/dak/config/debian-security"
+	;;
+    *)
+	configdir="/srv/ftp-master.debian.org/dak/config/debian"
+	;;
+esac
+. "$configdir/vars"
+
+# Read and trivially validate our configuration
+. "$configdir/byhand-code-sign.conf"
+for var in EFI_BINARY_PRIVKEY EFI_BINARY_CERT \
+	   LINUX_SIGNFILE LINUX_MODULE_PRIVKEY LINUX_MODULE_CERT; do
+	test -v $var || error "$var is not defined in configuration"
+	test -n "${!var}" || error "$var is empty in configuration"
+done
+
+TARGET="$ftpdir/dists/$SUITE/main/code-sign/"
+OUT_TARBALL="$TARGET/${IN_TARBALL##*/}"
+OUT_TARBALL="${OUT_TARBALL%.tar.xz}_sigs.tar.xz"
+
+# Check that this source/arch/version hasn't already been signed
+if [ -e "$OUT_TARBALL" ]; then
+	error "Signature tarball already exists: $OUT_TARBALL"
+fi
+
+# If we fail somewhere, cleanup the temporary directories
+IN_DIR=
+OUT_DIR=
+CERT_DIR=
+cleanup() {
+	for dir in "$IN_DIR" "$OUT_DIR" "$CERT_DIR"; do
+		test -z "$dir" || rm -rf "$dir"
+	done
+}
+trap cleanup EXIT
+
+# Extract the data into the input directory
+IN_DIR="$(mktemp -td byhand-code-sign-in.XXXXXX)"
+tar xaf "$IN_TARBALL" --directory="$IN_DIR"
+
+case "$EFI_BINARY_PRIVKEY" in
+    pkcs11:*)
+	# Translate from OpenSSL PKCS#11 enigne syntax to pesign parameters
+	# See: https://sources.debian.net/src/engine-pkcs11/0.2.2-1/src/engine_pkcs11.c
+	pkcs11_pin_value=
+	old_IFS="$IFS"
+	IFS=';'
+	for kv in ${EFI_BINARY_PRIVKEY#pkcs11:}; do
+		case "$kv" in
+		    token=*)
+			pkcs11_token="${kv#*=}"
+			;;
+		    object=*)
+			pkcs11_object="${kv#*=}"
+			;;
+		    pin-value=*)
+			pkcs11_pin_value="${kv#*=}"
+			;;
+		esac
+	done
+	IFS="$old_IFS"
+	unset old_IFS
+	# TODO: unlock it
+	PESIGN_PARAMS=(-t "$pkcs11_token" -c "$pkcs11_object")
+	;;
+    *)
+	# Create certificate store for pesign
+	CERT_DIR="$(mktemp -td byhand-code-sign-cert.XXXXXX)"
+	chmod 700 "$CERT_DIR"
+	mkdir "$CERT_DIR/store"
+	certutil -N --empty-password -d "$CERT_DIR/store"
+	openssl pkcs12 -export \
+		-inkey "$EFI_BINARY_PRIVKEY" -in "$EFI_BINARY_CERT" \
+		-out "$CERT_DIR/efi-image.p12" -passout pass: \
+		-name efi-image
+	pk12util -i "$CERT_DIR/efi-image.p12" -d "$CERT_DIR/store" -K '' -W ''
+	PESIGN_PARAMS=(-n "$CERT_DIR/store" -c efi-image)
+	;;
+esac
+
+# Create hierarchy of detached signatures in parallel to the uploaded files
+OUT_DIR="$(mktemp -td byhand-code-sign-out.XXXXXX)"
+while read filename; do
+	mkdir -p "$OUT_DIR/${filename%/*}"
+	case "${filename##*/}" in
+	    *.efi | vmlinuz-*)
+		pesign -i "$IN_DIR/$filename" \
+		       --export-signature "$OUT_DIR/$filename.sig" --sign \
+		       -d sha256 "${PESIGN_PARAMS[@]}"
+		;;
+	    *.ko)
+		"$LINUX_SIGNFILE" -d sha256 "$LINUX_MODULE_PRIVKEY" \
+			"$LINUX_MODULE_CERT" "$IN_DIR/$filename"
+		mv "$IN_DIR/$filename.p7s" "$OUT_DIR/$filename.sig"
+		;;
+	    *)
+		echo >&2 "W: Not signing unrecognised file: $filename"
+		continue
+		;;
+	esac
+	if [ ${#filename} -gt 60 ]; then
+		filename_trunc="...${filename:$((${#filename} - 57)):57}"
+	else
+		filename_trunc="$filename"
+	fi
+	printf 'I: Signed %-60s\r' "$filename_trunc"
+done < <(find "$IN_DIR" -type f -printf '%P\n')
+
+# Clear last progress message
+printf '%-70s\r' ''
+
+# Build tarball of signatures
+chmod -R a+rX "$OUT_DIR"
+mkdir -p "$TARGET"
+tar caf "$OUT_TARBALL" --directory="$OUT_DIR" .
+echo "I: Created $OUT_TARBALL"
+
+trap - EXIT
+cleanup
+
+exit 0

Attachment: signature.asc
Description: Digital signature


Reply to: